====== 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 =====