====== KingCon 4.0 - Neues Event aufsetzen ======
====== Variables ======
{PROJECT_NAME} : eec
{DOMAIN} : event.eec-2024.com
{DOMAIN_SLUG} : event-eec-2024-com
{WEBSITE_TITLE} : EEC (European Electric Steelmaking)
{EMAIL} : event@mail.eec-2024.com
{EMAIL_SERVER} : srv03.tema-hosting.de
{EMAIL_PASS} : ***
{NODE_PORT} : 15165
{PROJECT_NAME_TO_COPY_FROM} : startup-the-future
{NEXT_FREE_REDIS_INSTANCE_ID_FOR_CELERY} : 5
{NEXT_FREE_REDIS_INSTANCE_ID_FOR_CACHING} : 6
Everywhere these placeholders are used, they need to be replaced with the variable content
===== Prepare new Event =====
==== 1. Log in to the server as root ====
ssh root@193.254.190.30 -p 12035
enter password, if prompted
==== 2. Setup domain in nginx ====
cd /etc/nginx/conf.d
nano {PROJECT_NAME}.conf
Enter the following, and save the file:
server {
listen 80;
listen [::]:80;
server_name {DOMAIN} ;
location ^~ /.well-known/acme-challenge {
default_type text/plain;
root /var/www/letsencrypt;
}
location / {
return 301 https://{DOMAIN}$request_uri;
}
}
Check if your config is valid:
nginx -t
should return
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
restart nginx
service nginx reload
==== 3. Get Let's Encrypt certificates ====
create directory for certificates
mkdir /etc/ssl/{PROJECT_NAME}
chown root:www-data /etc/ssl/{PROJECT_NAME}
chmod -R 755 /etc/ssl/{PROJECT_NAME}
acme.sh --issue -w /var/www/letsencrypt -d {DOMAIN} --keylength ec-384 --key-file /etc/ssl/{PROJECT_NAME}/{DOMAIN_SLUG}.key --fullchain-file /etc/ssl/{PROJECT_NAME}/{DOMAIN_SLUG}.crt --reloadcmd "systemctl reload nginx"
Should end with
[...] Installing key to: /etc/ssl/{PROJECT_NAME}/{DOMAIN_SLUG}.key
[...] Installing full chain to: /etc/ssl/{PROJECT_NAME}/{DOMAIN_SLUG}.crt
[...] Run reload cmd: systemctl reload nginx
[...] Reload success
==== 4. Generate dhparams ====
openssl dhparam -out /etc/ssl/{PROJECT_NAME}/ffdhe4096 4096
==== 5. Setup uWSGI for KingCon 4.0 ====
=== create new wsgi config ===
nano /etc/uwsgi-{PROJECT_NAME}.ini
[uwsgi]
uid = {PROJECT_NAME}
gid = nginx
umask = 027
processes = 4
enable-threads = true
chmod-socket = 770
chown-socket = {PROJECT_NAME}:nginx
socket = /opt/{PROJECT_NAME}/web/uwsgi.sock
stats = /opt/{PROJECT_NAME}/web/uwsgi-stats.sock
protocol = uwsgi
master = true
auto-procname = true
procname-prefix-spaced = {PROJECT_NAME}
disable-logging = true
single-interpreter = true
touch-reload = /opt/{PROJECT_NAME}/web/indico.wsgi
wsgi-file = /opt/{PROJECT_NAME}/web/indico.wsgi
virtualenv = /opt/{PROJECT_NAME}/.venv
vacuum = true
buffer-size = 20480
memory-report = true
max-requests = 2500
harakiri = 900
harakiri-verbose = true
reload-on-rss = 2048
evil-reload-on-rss = 8192
=== create Service ===
nano /etc/systemd/system/{PROJECT_NAME}-uwsgi.service
[Unit]
Description={WEBSITE_TITLE} uWSGI
After=network.target
[Service]
ExecStart=/opt/{PROJECT_NAME}/.venv/bin/uwsgi --ini /etc/uwsgi-{PROJECT_NAME}.ini
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
SyslogIdentifier={PROJECT_NAME}-uwsgi
User={PROJECT_NAME}
Group=nginx
UMask=0027
Type=notify
NotifyAccess=all
KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
==== 6. Create Celery Service for KingCon 4.0 ====
=== create Service ===
nano /etc/systemd/system/{PROJECT_NAME}-celery.service
[Unit]
Description={WEBSITE_TITLE} Celery
After=network.target
[Service]
ExecStart=/opt/{PROJECT_NAME}/.venv/bin/indico celery worker -B
Restart=always
SyslogIdentifier={PROJECT_NAME}-celery
User={PROJECT_NAME}
Group=nginx
UMask=0027
Type=simple
KillMode=mixed
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
==== 7. Create user and SWITCH to it ====
useradd -rm -g nginx -d /opt/{PROJECT_NAME} -s /bin/bash {PROJECT_NAME}
su - {PROJECT_NAME}
==== 8. Create virtual env ====
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
cat >> ~/.bashrc <<'EOF'
export PATH="/opt/{PROJECT_NAME}/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
EOF
source ~/.bashrc
==== 9. Install latest Python 3.9 ====
List the latest available Version of Python 3.9
pyenv install --list | egrep '^\s*3\.9\.'
Install latest version
pyenv install 3.9.x
pyenv global 3.9.x
Verify installation worked
python -V
Configuration/Updates/Dependancies
python -m venv --upgrade-deps --prompt kingcon ~/.venv
source ~/.venv/bin/activate
echo 'source ~/.venv/bin/activate' >> ~/.bashrc
pip install wheel
pip install uwsgi
==== 10. Create Directories ====
mkdir ~/archive
mkdir ~/cache
mkdir ~/container
mkdir ~/custom
mkdir ~/etc
mkdir ~/log
mkdir ~/log/nginx
mkdir ~/packages
mkdir ~/tmp
mkdir ~/web
chmod go-rwx ~/* ~/.[^.]*
chmod 710 ~/ ~/archive ~/cache ~/log ~/tmp
chmod 750 ~/web ~/.venv
chmod g+w ~/log/nginx
===== Copy packages + container to server =====
open a new terminal and switch to your indico development directory
scp -P 12035 -r deployment/docker/indico-base/packages/ root@193.254.190.30:/opt/{PROJECT_NAME}/
===== Copy custom templates from other event =====
cp -r /opt/{PROJECT_NAME_TO_COPY_FROM}/custom/* /opt/{PROJECT_NAME}/custom/
chown -R {PROJECT_NAME}:nginx /opt/{PROJECT_NAME}/custom
find /opt/{PROJECT_NAME}/custom -type d -exec chmod 755 {} \;
find /opt/{PROJECT_NAME}/custom -type f -exec chmod 644 {} \;
===== Setup Database =====
Execute the following commands to create a new database as root on the server
su - postgres -c 'createuser {PROJECT_NAME}'
su - postgres -c 'createdb -E UTF8 -T template0 -O {PROJECT_NAME} {PROJECT_NAME}'
su - postgres -c 'psql {PROJECT_NAME} -c "CREATE EXTENSION unaccent; CREATE EXTENSION pg_trgm;"'
===== Install and configure Indico =====
Go back to the server terminal and log in with the user for the project {PROJECT_NAME}
==== 1. Install Indico ====
install the latest indico package
pip install -U packages/indico-3.*-py3-none-any.whl
==== 2. Install all Plugins ====
install the latest default Indico plugins
pip install indico-plugins
install the latest TEMA plugin packages
pip install -U packages/indico_plugin_*-py3-none-any.whl
==== 3. Run setup wizard ====
indico setup wizard
Please answer everything according to the following script
Enter the base directory where Indico will be installed.
Indico root path: /opt/{PROJECT_NAME}
Indico will use the following directories
/opt/eec/archive *
/opt/eec/cache *
/opt/eec/log *
/opt/eec/tmp *
/opt/eec/etc *
/opt/eec/web *
The directories marked with a * already exist. We strongly recommend installing Indico in a new directory that contains nothing but the Python virtualenv. If you are upgrading from Indico v1.2, please move its data to a different location.
Continue anyway? [y/N]: y
Indico needs to know the URL through which it is accessible. We strongly recommend using an https:// URL and a subdomain, e.g.
https://indico.yourdomain.com
Indico URL: https://{DOMAIN}
Enter the SQLAlchemy connection string to connect to your PostgreSQL database.
For a remote database, use postgresql://user:pass@host/dbname
PostgreSQL database URI: postgresql:///{PROJECT_NAME}
Indico uses Redis to manage scheduled/background tasks. Enter the URL to your
Redis server. Running one locally is usually the easiest option.
Redis URI (celery): redis://127.0.0.1:6379/{NEXT_FREE_REDIS_INSTANCE_ID_FOR_CELERY}
Redis is also used for caching. We recommend using a separate redis database,
which allows you to clear the cache without affecting celery
Redis URI (cache): redis://127.0.0.1:6379/{NEXT_FREE_REDIS_INSTANCE_ID_FOR_CACHING}
The Contact page displays this email address to users. If empty, the Contact
page will be hidden.
Contact email: {EMAIL}
If an error occurs Indico sends an email to the admin address. This should be the address of whoever is the technical manager of this Indico instance, i.e. most likely you.
Admin email: {EMAIL}
When Indico sends email notifications they are usually sent from the noreply email.
No-reply email: {EMAIL}
Indico needs an SMTP server to send emails.
SMTP host: {EMAIL_SERVER}
SMTP port: 25
If your SMTP server requires authentication, enter the username now.
SMTP username: {EMAIL}
SMTP password: ***
SMTP connection failed: [Errno -2] Name or service not known
Keep these settings anyway? [y/N]: y
Specify the default language/locale used by Indico.
Default locale: en_GB
Specify the default timezone used by Indico.
Default timezone: Europe/Berlin
Indico contains a room booking system. If you do not plan to maintain a list
of rooms available in your organization in Indico and use it to book them, it
is recommended to leave the room booking system disabled.
Enable room booking? [y/N]: N
Indico can show important system notices (e.g. about security issues) to
administrators. They are retrieved once a day without sending any data related
to your Indico instance. It is strongly recommended to enable them.
Enable system notices? [Y/n]: y
By creating a symlink to indico.conf in /opt/eec/.indico.conf, you can run
indico without having to set the INDICO_CONFIG environment variable
Create symlink? [Y/n]: Y
Creating /opt/{PROJECT_NAME}/etc/indico.conf
Copying /opt/{PROJECT_NAME}/.venv/lib/python3.9/site-packages/indico/logging.yaml.sample -> /opt/{PROJECT_NAME}/etc/logging.yaml
Linking /opt/{PROJECT_NAME}/web/static -> /opt/{PROJECT_NAME}/.venv/lib/python3.9/site-packages/indico/web/static
Copying /opt/{PROJECT_NAME}/.venv/lib/python3.9/site-packages/indico/web/indico.wsgi -> /opt/{PROJECT_NAME}/web/indico.wsgi
Linking /opt/{PROJECT_NAME}/.indico.conf -> /opt/{PROJECT_NAME}/etc/indico.conf
Indico has been configured successfully!
You can now run indico db prepare to initialize your Indico database
==== 4. Append custom settings to config file ====
**About locales:**
for only German use:
DEFAULT_LOCALE = 'de_DE'
CUSTOM_LANGUAGES = {'en_GB': None, 'de_DE': ('Deutsch', '')}
for only English use:
DEFAULT_LOCALE = 'en_GB'
CUSTOM_LANGUAGES = {'en_GB': ('English', ''), 'de_DE': None}
for English and German use:
DEFAULT_LOCALE = 'en_GB'
CUSTOM_LANGUAGES = {'en_GB': ('English', ''), 'de_DE': ('Deutsch', '')}
# General settings
SQLALCHEMY_DATABASE_URI = 'postgresql:///{PROJECT_NAME}'
SECRET_KEY = b'...'
BASE_URL = 'https://{DOMAIN}'
CELERY_BROKER = 'redis://127.0.0.1:6379/{NEXT_FREE_REDIS_INSTANCE_ID_FOR_CELERY}'
REDIS_CACHE_URL = 'redis://127.0.0.1:6379/{NEXT_FREE_REDIS_INSTANCE_ID_FOR_CACHING}'
DEFAULT_TIMEZONE = 'Europe/Berlin'
DEFAULT_LOCALE = {DEFAULT_LOCALE}
ENABLE_ROOMBOOKING = False
CACHE_DIR = '/opt/{PROJECT_NAME}/cache'
TEMP_DIR = '/opt/{PROJECT_NAME}/tmp'
LOG_DIR = '/opt/{PROJECT_NAME}/log'
STORAGE_BACKENDS = {'default': 'fs:/opt/{PROJECT_NAME}/archive'}
ATTACHMENT_STORAGE = 'default'
STATIC_FILE_METHOD = ('xaccelredirect', {'/opt/{PROJECT_NAME}': '/.xsf/{PROJECT_NAME}'})
# Email settings
SMTP_SERVER = ('{EMAIL_SERVER}', 25)
SMTP_USE_TLS = True
SMTP_LOGIN = '{EMAIL}'
SMTP_PASSWORD = '{EMAIL_PASS}'
SUPPORT_EMAIL = '{EMAIL}'
PUBLIC_SUPPORT_EMAIL = ''
NO_REPLY_EMAIL = '{EMAIL}'
# Plugins
PLUGINS = {'payment_manual','ursh', 'abstract_status', 'tema_theme', 'favicons', 'payment_invoice', 'emails', 'cookies'}
# Customization settings
CUSTOMIZATION_DIR = '/opt/{PROJECT_NAME}/custom'
CUSTOM_LANGUAGES = {CUSTOM_LANGUAGES}
==== 5. Prepare the Database ====
indico db prepare
indico db --all-plugins upgrade
===== Send HTTPs Traffic to indico instance =====
==== 1. Create new config to route https traffic ====
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {DOMAIN};
ssl_certificate /etc/ssl/{PROJECT_NAME}/{DOMAIN_SLUG}.crt;
ssl_certificate_key /etc/ssl/{PROJECT_NAME}/{DOMAIN_SLUG}.key;
ssl_dhparam /etc/ssl/{PROJECT_NAME}/ffdhe4096;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
access_log /opt/{PROJECT_NAME}/log/nginx/access.log combined;
error_log /opt/{PROJECT_NAME}/log/nginx/error.log;
location ^~ /.well-known/acme-challenge {
default_type text/plain;
root /var/www/letsencrypt;
}
location /.xsf/{PROJECT_NAME}/ {
internal;
alias /opt/{PROJECT_NAME}/;
}
location ~ ^/(images|fonts)(.*)/(.+?)(__v[0-9a-f]+)?\.([^.]+)$ {
alias /opt/{PROJECT_NAME}/web/static/$1$2/$3.$5;
access_log off;
}
location ~ ^/(css|dist|images|fonts)/(.*)$ {
alias /opt/{PROJECT_NAME}/web/static/$1/$2;
access_log off;
}
location /robots.txt {
alias /opt/{PROJECT_NAME}/web/static/robots.txt;
access_log off;
}
# disable unwanted indico functions
location ~* ^\/event\/\d+\/registrations\/\d+\/\d+\/avatar {
# disable the avatar, because it could be used to know how many persons are already registered
return 301 /404;
}
# pass new stuff to node app
location ~* ^\/(_next|__nextjs|frontend-assets|404|unauthorized|admin\/(accounting-entities|tax-rates|cookies|invoices)).* {
proxy_pass http://127.0.0.1:{NODE_PORT};
}
# pass invoicing settings to node app
location ~* ^\/event\/\d+\/manage\/(invoicing|invoice|tickets).* {
proxy_pass http://127.0.0.1:{NODE_PORT};
}
# pass event pages to node app
location ~* "^\/event\/\d+(\/registrations|\/timetable){0,1}(\/){0,1}$" {
proxy_pass http://127.0.0.1:{NODE_PORT};
}
# pass public ticket view to node app
location ~* "^\/event\/\d+\/tickets\/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\- [0-9a-fA-F]{12}$" {
proxy_pass http://127.0.0.1:{NODE_PORT};
}
# pass root url to node app
location = / {
proxy_pass http://127.0.0.1:{NODE_PORT};
}
location / {
root /var/empty/nginx;
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/opt/{PROJECT_NAME}/web/uwsgi.sock;
uwsgi_param UWSGI_SCHEME $scheme;
uwsgi_read_timeout 15m;
uwsgi_buffers 32 32k;
uwsgi_busy_buffers_size 128k;
uwsgi_hide_header X-Sendfile;
client_max_body_size 1G;
}
}
==== 2. Check that the config is valid ====
nginx -t
should return
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
==== 3. Restart nginx ====
service nginx reload
===== Start Services and create default user =====
systemctl restart {PROJECT_NAME}-celery.service {PROJECT_NAME}-uwsgi.service
systemctl enable {PROJECT_NAME}-celery.service {PROJECT_NAME}-uwsgi.service
Open
https://{DOMAIN}/bootstrap
in your Browser
===== Start a container for the node frontend =====
Wie das Docker-Image für die Node-Anwendung entsteht (und auf den Indico-Server gelangt), steht beispielhaft hier: [[projekte:indico:kingcon_4.0_-_node_im_container|Node im Container]]
cd /opt/{PROJECT_NAME}/container
ls -l
Da sollte eine Datei **{PROJECT_NAME}-production-//DATESTAMP//.tar** liegen.
docker load < {PROJECT_NAME}-production-{DATESTAMP}.tar
docker image ls
docker container ls
Wir sehen unser geladenes Image. Und wir sehen, dass unser Image noch nicht "läuft".
docker run -d -p 127.0.0.1:{NODE_PORT}:3000 --restart unless-stopped {PROJECT_NAME}-production
docker container ls
Jetzt sollte
https://{DOMAIN}/
keinen "bad gateway"-Fehler mehr liefern.
Für eine nutzbare Ansicht müssen nun Farben und Bilder in den Theme-Plugins definiert werden. \\ Siehe https://kingcon-docs.tema-hosting.de/
===== Unterprojekte =====
{{indexmenu>projekte:kingcon_register-me.org:kingcon_4.0_-_neues_event_aufsetzen#2| js doku}}
\\
Neues Projekt anlegen: {{NEWPAGE>projekte:kingcon_register-me.org:kingcon_4.0_-_neues_event_aufsetzen}}
===== Kommentare =====