Commit f4e3f15c authored by HQ's avatar HQ
Browse files

Various improvements

parent 54e00be1
VERSION=1.0a
REBASE=0
MAINTAINER=Christian Orellana <christian@origo.io>
BASEIMAGE=ubuntu-xenial.1.5.master.qcow2
BASESUITE=
NAME=discourse
APPNAME=Discourse
DIR=files
DIRTARGET=/tmp
TAR=
TARTARGET=
GIT=https://github.com/discourse/discourse.git
GITTARGET=/var/discourse
PREEXEC=/tmp/files/preexec.sh
DEBS=postgresql-9.5 libgdbm-dev libncurses5-dev automake libtool bison libffi-dev gawk g++ libssl-dev make zlib1g-dev libyaml-dev libsqlite3-dev sqlite3 libgmp-dev pkg-config libgmp-dev libreadline6-dev libpq-dev redis-server ruby-rmagick imagemagick optipng jhead jpegoptim gifsicle postfix software-properties-common ruby-sidekiq-cron npm
POSTEXEC=/tmp/files/postexec.sh
SERVICE=/usr/local/bin/stabile-discourse.pl
TERMINALLINK=/stabile/pipe/http://{uuid}:4200
PRICE=-420
VCPU=2
MEMORY=4096
LOGO=https://www.stabile.io/images/apps/logo-discourse.png
THUMBNAIL=https://www.stabile.io/images/apps/thumb-discourse.png
SUMMARY=Discourse is a civilized discussion platform. Use it as a mailing list, forum, long-form chat room, and more!
DESCRIPTION=Discourse is a from-scratch reboot, an attempt to reimagine what a modern Internet discussion platform should be today, in a world of ubiquitous smartphones, tablets, Facebook, and Twitter. \
<h2>We're civilized.</h2> \
Our trust system means that the community builds a natural immune system to defend itself from trolls, bad actors, and spammers — and the most engaged community members can assist in the governance of their community. We put a trash can on every street corner with a simple, low-friction flagging system. Positive behaviors are encouraged through likes and badges. We gently, constantly educate members in a just-in-time manner on the universal rules of civilized discourse.\
<h2>Uncompromisingly open source.</h2> \
There is only one version of Discourse - the awesome open source version. There's no super secret special paid commercial version with better or more complete features. Because Discourse is 100% open source, now and forever, it belongs to you as much as it belongs to us. That's how community works.<br> \
Everything that most communities would want is included out of the box; a giant collection of complex plugins should not be required to have a great experience. \
<h2>Simple. Modern. Fun.</h2> \
Discourse pares all the complexity away and puts just the essential stuff on screen - the conversations you care most about, based on your participation.<br> \
All the modern amenities you'd expect from a big social website like Twitter or Facebook are present in Discourse. Mention someone by @name. Paste in a link or an image, and we make it awesome on your behalf. Simple quoting and linking of replies and topics. Reply wherever you are, online or via email.<br> \
And it "just works" on your phone and tablet.
#!/bin/bash
apt-add-repository -y ppa:brightbox/ruby-ng
apt-get update
apt-get -q -y --force-yes install ruby2.4 ruby2.4-dev
cp /var/discourse/config/discourse_defaults.conf /var/discourse/config/discourse.conf
perl -pi -e 's/db_host =.*/db_host = localhost/g' /var/discourse/config/discourse.conf
perl -pi -e 's/db_port =.*/db_port = 5432/g' /var/discourse/config/discourse.conf
perl -pi -e 's/db_password =.*/db_password = \"password\"/g' /var/discourse/config/discourse.conf
perl -pi -e 's/hostname =.*/hostname = discourse.stabile.io/g' /var/discourse/config/discourse.conf
perl -pi -e 's/smtp_address =.*/smtp_address = localhost/g' /var/discourse/config/discourse.conf
perl -pi -e 's/smtp_domain =.*/smtp_domain = stabile.io/g' /var/discourse/config/discourse.conf
perl -pi -e 's/smtp_authentication =.*/smtp_authentication = none/g' /var/discourse/config/discourse.conf
perl -pi -e 's/smtp_enable_start_tls =.*/smtp_enable_start_tls = false/g' /var/discourse/config/discourse.conf
perl -pi -e 's/APP_ROOT =.*/APP_ROOT = "\/var\/discourse\"/g' /var/discourse/config/puma.rb
perl -pi -e 's/daemonize .*/daemonize true\n bind "tcp:\/\/0.0.0.0:9292"/g' /var/discourse/config/puma.rb
perl -pi -e 's/development test profile/development production test profile/g' /var/discourse/config/application.rb
perl -pi -e 's/(.*config.serve_static_files.+)/\#$1/g' /var/discourse/config/environments/production.rb
npm install -g svgo
ln -s /usr/bin/nodejs /usr/bin/node
perl -pi -e 's/inet_protocols =.*/inet_protocols = ipv4/;' /etc/postfix/main.cf
echo 'production:
prepared_statements: false
adapter: postgresql
database: discourse
min_messages: warning
pool: 5
timeout: 5000
host_names: localhost' >> /var/discourse/config/database.yml
echo "---
:concurrency: 5
:pidfile: tmp/pids/sidekiq.pid
staging:
:concurrency: 10
production:
:concurrency: 20
:queues:
- [critical,4]
- [default, 2]
- [low]
development:
:queues:
- [critical,4]
- [default, 2]
- [low]" > /var/discourse/config/sidekiq.yml
mkdir -p /var/discourse/tmp/sockets
mkdir -p /var/discourse/tmp/pids
gem install bundler
cd /var/discourse ; bundle install
echo "export RAILS_ENV=production" >> /etc/bash.bashrc
# Remove tabs from Webmin UI
rm -r /usr/share/webmin/stabile/tabs/commands
rm -r /usr/share/webmin/stabile/tabs/servers
cp -a /tmp/files/stabile/tabs/discourse /usr/share/webmin/stabile/tabs/
cp /tmp/files/stabile-discourse.pl /usr/local/bin/
# Change logo
perl -pi -e 's/images\/ubuntu-logo.png/tabs\/rocketchat\/logo-discourse.png/' /usr/share/webmin/stabile/index.cgi
#!/bin/bash
# This script is executed in the image chroot
echo "Performing pre-install operations"
#!/usr/bin/perl
use JSON;
unless (-e '/etc/discourse.seeded') {
if (`grep ProxyPass /etc/apache2/sites-available/000-default.conf`) {
print `perl -pi -e 's/.*ProxyPass.*\\n//g' /etc/apache2/sites-available/000-default.conf`;
print `perl -pi -e 's/.*ProxyPass.*\\n//g' /etc/apache2/sites-available/default-ssl.conf`;
print `perl -pi -e 's/.*ProxyPass.*\\n//g' /etc/apache2/sites-available/000-default-le-ssl.conf`;
}
print `echo "<h1 align=center><img width=48 height=48 src=https://www.origo.io/images/apps/thumb-discourse.png> Preparing Discourse...</h1><p align=center><img src=https://www.origo.io/images/39.svg></p><script>setTimeout(function(){location.reload() ; }, 8000);</script>" > /var/www/html/index.html`;
print `sudo -u postgres psql -c "CREATE DATABASE discourse;"`;
print `sudo -u postgres psql -c "CREATE USER discourse;"`;
print `sudo -u postgres psql -c "ALTER USER discourse WITH ENCRYPTED PASSWORD 'password';"`;
print `sudo -u postgres psql -c "ALTER DATABASE discourse OWNER TO discourse;"`;
print `sudo -u postgres psql -c "CREATE ROLE root WITH CREATEDB LOGIN CREATEROLE SUPERUSER;"`;
print `sudo -u postgres psql discourse -c "CREATE EXTENSION hstore;"`;
print `sudo -u postgres psql discourse -c "CREATE EXTENSION pg_trgm;"`;
print `cd /var/discourse ; RAILS_ENV=production bundle exec rake db:migrate`;
print `cd /var/discourse ; RAILS_ENV=production bundle exec rake assets:precompile`;
my $email = `curl -k --silent https://10.0.0.1/stabile/users/me/username`;
chomp $email;
print "Adding user $email\n";
my $randpass = `openssl rand -base64 24`;
chomp $randpass;
print `cd /var/discourse ; export RAILS_ENV=production; echo "$email\n$randpass\n$randpass\nY " | rake admin:create`;
unless (`grep ProxyPass /etc/apache2/sites-available/000-default.conf`) {
print `perl -pi -e 's/(DocumentRoot .*)/\$1\\nProxyPass \\/ http:\\/\\/127.0.0.1:9292\\/\\nProxyPassReverse \\/ http:\\/\\/127.0.0.1:9292\\//g' /etc/apache2/sites-available/000-default.conf`;
print `perl -pi -e 's/(DocumentRoot .*)/\$1\\nProxyPass \\/ http:\\/\\/127.0.0.1:9292\\/\\nProxyPassReverse \\/ http:\\/\\/127.0.0.1:9292\\//g' /etc/apache2/sites-available/default-ssl.conf`;
}
`systemctl restart apache2`;
my $appinfo = `curl -sk https://10.0.0.1/stabile/servers?action=getappinfo`;
my $info_ref = from_json($appinfo);
my $externalip = `cat /tmp/externalip`;
chomp $externalip;
my $hostname = $externalip . '.' . $info_ref->{dnsdomain};
`perl -pi -e 's/hostname =.*/hostname = $hostname/g' /var/discourse/config/discourse.conf`;
`perl -pi -e 's/smtp_domain =.*/smtp_domain = $hostname/g' /var/discourse/config/discourse.conf`;
`perl -pi -e 's/myhostname =.*/myhostname = $hostname/g' /var/discourse/config/discourse.conf`;
print `sudo -u postgres psql discourse -c "UPDATE site_settings SET value = 'noreply\@$hostname' WHERE name = 'notification_email';"`;
`systemctl restart postfix`;
`touch /etc/discourse.seeded`;
}
if (-e "/etc/apache2/sites-available/000-default-le-ssl.conf" && !(`grep ProxyPass /etc/apache2/sites-available/000-default-le-ssl.conf`)) {
print `perl -pi -e 's/(DocumentRoot .*)/\$1\\nProxyPass \\/ http:\\/\\/127.0.0.1:9292\\/\\nProxyPassReverse \\/ http:\\/\\/127.0.0.1:9292\\//g' /etc/apache2/sites-available/000-default-le-ssl.conf`;
`systemctl restart apache2`;
}
print `cd /var/discourse ; RAILS_ENV=production bundle exec puma -C config/puma.rb`;
print `cd /var/discourse ; RAILS_ENV=production bundle exec sidekiq -l log/sidekiq.log -C config/sidekiq.yml &`;
## this is the all-in-one, standalone Discourse Docker container template
##
## After making changes to this file, you MUST rebuild
## /var/discourse/launcher rebuild app
##
## BE *VERY* CAREFUL WHEN EDITING!
## YAML FILES ARE SUPER SUPER SENSITIVE TO MISTAKES IN WHITESPACE OR ALIGNMENT!
## visit http://www.yamllint.com/ to validate this file as needed
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
#- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
## which TCP/IP ports should this container expose?
## If you want Discourse to share a port with another webserver like Apache or nginx,
## see https://meta.discourse.org/t/17247 for details
expose:
- "8080:80" # http
# - "1443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## Set db_shared_buffers to a max of 25% of the total memory.
## will be set automatically by bootstrap based on detected RAM, or you can override
db_shared_buffers: "1024MB"
## can improve sorting performance, but adds memory usage per-connection
#db_work_mem: "40MB"
## Which Git revision should this container use? (default: tests-passed)
#version: tests-passed
env:
LANG: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## How many concurrent web requests are supported? Depends on memory and CPU cores.
## will be set automatically by bootstrap based on detected CPUs, or you can override
UNICORN_WORKERS: 2
## TODO: The domain name this Discourse instance will respond to
DISCOURSE_HOSTNAME: discourse
## Uncomment if you want the container to be started with the same
## hostname (-h option) as specified above (default "$hostname-$config")
#DOCKER_USE_HOSTNAME: true
## TODO: List of comma delimited emails that will be made admin and developer
## on initial signup example 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: 'christian@os2cloud.dk'
## TODO: The SMTP mail server used to validate new accounts and send notifications
DISCOURSE_SMTP_ADDRESS: localhost
DISCOURSE_SMTP_PORT: 25
DISCOURSE_SMTP_USER_NAME: discourse
DISCOURSE_SMTP_PASSWORD: "dummy"
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (optional, default true)
## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
#LETSENCRYPT_ACCOUNT_EMAIL: me@example.com
## The CDN address for this Discourse instance (configured to pull)
## see https://meta.discourse.org/t/14857 for details
#DISCOURSE_CDN_URL: //discourse-cdn.example.com
## The Docker container is stateless; all data is stored in /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## Plugins go here
## see https://meta.discourse.org/t/19157 for details
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## Any custom commands to run after building
run:
- exec: echo "Beginning of custom commands"
## If you want to set the 'From' email address for your first registration, uncomment and change:
## After getting the first signup email, re-comment the line. It only needs to run once.
#- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
- exec: echo "End of custom commands"
#!/usr/bin/perl
use JSON;
my $dnsdomain = $appinfo{dnsdomain};
my $dnssubdomain = $appinfo{'dnssubdomain'};
my $dom = ($dnsdomain && $dnssubdomain)?"$externalip.$dnssubdomain.$dnsdomain":"$externalip";
sub discourse {
my $action = shift;
my $in_ref = shift;
my %in = %{$in_ref};
if ($action eq 'form') {
my $form;
my $meref = show_me();
my $email = $meref->{username};
# Redirect to upgrade page if still upgrading
if (-e "/tmp/restoring") {
$form .= qq|<script>loc=document.location.href; setTimeout(function(){document.location=loc;}, 1500); </script>|;
}
$form .= <<END
<div class="tab-pane container" id="discourse">
<div>
Here you can manage basic security for Discourse.
</div>
<small>Set password for Discourse user "$email":</small>
<form class="passwordform" action="index.cgi?action=discoursepassword&tab=discourse" method="post" onsubmit="discourseSpinner(); \$('#discoursepassword').val(''); return false;" accept-charset="utf-8" id="discoursepassword_form" autocomplete="off">
<div class="row">
<div class="col-sm-10">
<input type="password" name="discoursepassword" id="discoursepassword" autocomplete="off" value="" class="password">
</div>
<div class="col-sm-2">
<button class="btn btn-default" type="submit" id="discoursepassword_button">Set!</button>
</div>
</div>
</form>
<small style="margin-top:10px;">
After setting the password <a target="_blank" href="https://$dom">log in here</a> with username "$email" and your password.
</small>
</div>
END
;
return $form;
} elsif ($action eq 'js') {
# Generate and return javascript the UI for this tab needs
my $js = <<END
\$("#currentwp").attr("href", "https://$dom/");
\$("#currentwp").text("to Discourse");
\$("#currentwp").parent().show()
function discourseSpinner(target) {
if (!target) target = "discoursepassword";
\$("#" + target + "_button").prop("disabled", true ).html('Set! <i class="fa fa-cog fa-spin"></i>');
var ser = \$('#' + target + '_form').serialize();
\$.post('index.cgi?action=' + target + '&tab=discourse', ser, function(data) {}
,'json'
).done(function( data ) {
salert(data.message);
\$("#" + target + "_button").prop("disabled", false ).html('Set!');
}).fail(function() {
salert( "An error occurred :(" );
\$("#" + target + "_button").prop("disabled", false ).html('Set!');
});
}
END
;
return $js;
# This is called from index.cgi (the UI)
} elsif ($action eq 'upgrade') {
my $res;
return $res;
# This is called from origo-ubuntu.pl when rebooting and with status "upgrading"
} elsif ($action eq 'restore') {
my $res;
return $res;
} elsif ($action eq 'discoursepassword' && defined $in{discoursepassword}) {
my $message;
my $meref = show_me();
my $email = $meref->{username};
my $pwd = $in{discoursepassword};
if ($pwd) {
my $res = `cd /var/discourse ; export RAILS_ENV=production; echo "$email\nY\n$pwd\n$pwd\nY " | rake admin:create 2>&1`;
$message .= $res if ($res =~ /error/i);
$message .= "The Discourse password was changed for $email!";
}
return qq|Content-type: application/json\n\n{"message": "$message"}|;
}
}
1;
......@@ -27,7 +27,7 @@ sub jupyter {
Here you can manage basic security for your Jupyter Notebook.
</div>
<small>Set the password for your Jupyter notebook:</small>
<form class="passwordform" action="index.cgi?action=jupyterpassword&tab=jupyter" method="post" onsubmit="limitJupyterSpinner(); \$('#jupyterpassword').val(''); return false;" accept-charset="utf-8" id="jupyterpassword_form" autocomplete="off">
<form class="passwordform" action="index.cgi?action=jupyterpassword&tab=jupyter" method="post" onsubmit="jupyterSpinner(); \$('#jupyterpassword').val(''); return false;" accept-charset="utf-8" id="jupyterpassword_form" autocomplete="off">
<div class="row">
<div class="col-sm-10">
<input type="password" name="jupyterpassword" id="jupyterpassword" autocomplete="off" value="" class="password"">
......@@ -53,7 +53,7 @@ END
\$("#currentwp").text("to Jupyter Notebook");
\$("#currentwp").parent().show()
function limitJupyterSpinner(target) {
function jupyterSpinner(target) {
if (!target) target = "jupyterpassword";
\$("#" + target + "_button").prop("disabled", true ).html('Set! <i class="fa fa-cog fa-spin"></i>');
var ser = \$('#' + target + '_form').serialize();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment