Landingpage

Landing page for I01/VERDA services: https://gitlab.plantmicrobe.de/i01-private/i01-landingpage/-/tree/main

Tech stack:

If you would like to add articles or contribute to the code, check the documentation section.

Setup environment

Node.js

Setup npm and make sure to have at least node version 20

nvm install v20
nvm use v20

Install the needed packages inside your repo root

npm install

SMTP server

If you want to make full use of the contact form, you need to provide a full SMTP configuration! Create an .env file inside the app root.

ENV variable Definition
SMTP_USERNAME Username for respective SMTP host
SMTP_PASSWORD Password for respective SMTP host
SMTP_HOST SMTP server of your choice
SMTP_PORT SMTP port of that server
FROM_ADDRESS Address which sends the mail (NOT the user input)
TO_ADDRESS Designated (support) mail address(es). Provide array for multiple recipients [...]
CC_ADDRESS Optional CC address(es). Provide array for multiple recipients [...]

Example:

SMTP_USERNAME=<YOUR USER NAME>
SMTP_PASSWORD=<SMTP HOST PASSWORD> 
SMTP_HOST=<POSTOUT SERVER>
SMTP_PORT=<POSTOUT PORT>
FROM_ADDRESS=<ANY VALID MAIL ADDRESS>
TO_ADDRESS=<MAIN RECIPIENT>
# Optional
CC_ADDRESS=<OPTIONAL RELATED RECIPIENTS>

If you run dev mode, nodemailer will create a throw-away Ethereal Account. No actual mail will be sent, but you can check it out at the provided URL (CLI output)

Local Usage

Development

Run on localhost using the following command. Be aware that this is for development/testing only. See below for production deployment!

npm run dev -- --host

Test Build

In case you want to verify the actual build (changes some UI elements, SMTP, etc.), you can build the page and preview it:

npm run build
npm run preview -- --host

Deployment

Build site

(optional) Install adapter-node package

npm i -D @sveltejs/adapter-node

Build the site

npm run build

Run it directly

node build

Run as daemon

To run your page in the background and on reboot of the machine, configure a socket and activate it

Create the service: /etc/systemd/system/myapp.service

[Service]
User=<YOUR USER or DELETE IF SUDO>
Environment=NODE_ENV=production IDLE_TIMEOUT=60
ExecStart=/usr/bin/node /path/to/myapp/build

Create the socket: /etc/systemd/system/myapp.socket

[Socket]
ListenStream=3000

[Install]
WantedBy=sockets.target

Enable the socket to run on restart

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.socket

If you experience trouble starting up the daemon (e.g. “Bad Request” error), make sure you are using the correct node path/version by running which node inside the root directory of your page

Configure nginx

Add the my.subdomain.de file to /etc/nginx/sites-available

server {
    listen 80;
    server_name my.subdomain.de;

    # Redirect all HTTP to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name my.subdomain.de;

    ssl_certificate /etc/nginx/ssl/my.subdomain.de/my.subdomain.de.crt;
    ssl_certificate_key /etc/nginx/ssl/my.subdomain.de/my.subdomain.de.key;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;
    
    add_header Strict-Transport-Security "max-age=15768000"; # 6 months

    # Request ID tracing (allows end-to-end tracking of requests for better
    # troubleshooting)
    add_header X-Request-ID $request_id;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    # The request body is sent to the proxied server immediately as it is
    # received
    proxy_request_buffering off;
    # Sets the HTTP protocol v1.1 for proxying in order to not use the buffer
    # in case of chunked transfer encoding
    proxy_http_version 1.1;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
	limit_except GET HEAD POST { deny all; }
    }
    location /arcpub/ {
    	proxy_pass http://localhost:8000/;
	proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        limit_except GET HEAD POST { deny all; }
    }
    error_page 502 /custom_502.html;
    location = /custom_502.html {
        root /var/www/html;
        internal;
    }
}

Activate by creating a symbolic link

sudo ln -s /etc/nginx/sites-available/my.subdomain.de /etc/nginx/sites-enabled/my.subdomain.de

Make sure sites-enabled is included in /etc/nginx/nginx.conf

include /etc/nginx/sites-enabled/*;

Host arcpub

In case you want to host the arcpub UI as external service, you need to create a systemd service for it as well.

Follow the instructions in this repo, to setup arcpub on your machine (recommended: using pip): https://gitlab.plantmicrobe.de/i01-private/arcpub

Then create /etc/systemd/system/arcpub.service:

[Unit]
Description=arcpub
After=network.target

[Service]
WorkingDirectory=/path/to/arcpub
ExecStart=/path/to/arcpub/venv/bin/arcpub --interactive
Restart=on-failure
RestartSec=5
User=trradmin

[Install]
WantedBy=multi-user.target

Enable and run the service

systemctl daemon-reload
systemctl enable arcpub
systemctl start arcpub