Hosting Websites
Für alles was nicht sich mit Wordpress und Themes lösen lässt, gibt es auch die Möglichkeit Webspace für Nutzer anzulegen.
Entweder als Unterverzweichnis z.B. m18.uni-weimar.de/foo
oder als Subdomain der bau-ha.us
Domain z.B. foo.bau-ha.us
- es ist auch Möglich eigene Domains zu nutzen, wenn die A oder CNAME Records auf den m18-Server zeigen.
Die Idee ist, dass die User einen Account ohne root Rechte hat und alle Prozesse unter dem Nutzer laufen können.
ssh / sftp
Zugang läuft einfach via SSH oder SFTP. Damit kann man die Ordner auch lokal mounten z.B. in Nautilus/Dolphin. Für OS X gibt es MacFUSE. SSHFS für Windows 10
chroot / sftp only
# groupadd sftponly
# /etc/ssh/sshd_config
Match Group sftponly
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
PermitTunnel no
X11Forwarding no
Nutzer in sftponly
Gruppe hinzufügen:
# gpasswd -a USER sftponly
nginx
Unser Webserver ist nginx und hat sich als recht praktisch und flexibel erwiesen.
Unsere Konfiguration sieht so aus:
/etc/nginx/sites-available/ <- Ordner wo Konfiguration für Domains/Subdomains liegen.
/etc/nginx/sites-enabled/ <- Symlinks für aktive Domains
Zum Beispiel:
/etc/nginx/sites-enabled/m18 <- Konfiguration für die M18-Seite
/etc/nginx/sites-enabled/gitlab <- Konfiguration für das gitlab
User Accounts
Einfach einen neuen Nutzer mit adduser
anlegen und dem Nutzer zur Gruppe www-data
hinzufügen. Dann im Homeverzeichnis den Ordner public_html
anlegen.
Unterverzeichnis
Standardmäßig kann man über https://m18.uni-weimar.de/~nutzer
auf die Dateien im public_html
eines jeden Nutzers zugreifen. Das ist für statische Dateien ausreichend. Eventuell müssen die Berechtigungen angepasst werden, es genügt, wenn alle lesen können. Alternativ kann man den Nutzer zur www-data
Gruppe hinzufügen und den Zugriff für alle beschränken (chmod 770 /home/nutzer
).
Domain und Subdomain
Es gibt die Möglichkeit beliebig viele Subdomains für die bau-ha.us
Domain anzulegen. Wir haben auch ein Wildcard-SSL-Zertifikat für diese Domains.
Domains und Subdomains sollten als eigene Datei in /etc/nginx/sites-available/<domain.tld>
angelegt werden.
Neue Domains müssen entweder als CNAME
Record auf bau-ha.us
zeigen oder der A
Record muss auf die IP vom Server zeigen: 141.54.160.48
. Momentan ist auch alles nur IPv4 only.
Eine Beispielkonfiguration für eine statische Website als bau-ha.us
Subdomain mit TLS-Verschlüsselung würde so aussehen:
# cat /etc/nginx/sites-enabled/subdomain.bau-ha.us
## Redirects all HTTP traffic to the HTTPS host
server {
listen 0.0.0.0:80;
server_name subdomain.bau-ha.us;
server_tokens off;
return 301 https://$http_host$request_uri;
}
server {
listen 443 ssl http2;
server_name subdomain.bau-ha.us;
server_tokens off;
ssl on;
# tls zertifikate
ssl_certificate /etc/ssl/certs/bauhaus-bundle.crt;
ssl_certificate_key /etc/ssl/private/bauhaus.key;
ssl_trusted_certificate /etc/ssl/certs/startssl_trust_chain.pem;
# oscp stapling, damit seiten schneller laden
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;
ssl_stapling on;
ssl_stapling_verify on;
# security header, damit browser seite nur über tls ansteuern
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
location / {
root /home/user/public_html;
}
}
TLS / Let's Encrypt
Wir nutzen acme_tiny
für Let's Encrypt. Zertifikate sind in /etc/ssl/letsencrypt
. Dort gibt es auch ein renew.sh
Script zum automatischen Erneuern der Domains, was man in die crontab
packen kann.
acme.sh
acme.sh
macht das alles einfacher. alles zu acme_tiny
ist obsolet.
acme_tiny: Zertifikat für Domain erstellen.
Ausführliche Dokumentation auf GitHub
Private Key für Domain erstellen (RSA)
# cd /etc/ssl/letsencrypt
# openssl genrsa 4096 > subdomain.bau-ha.us.key
acme_tiny: CSR Request erstellen
# openssl req -new -sha256 \
-key subdomain.bau-ha.us.key \
-subj "/CN=subdomain.bau-ha.us" \
> subdomain.bau-ha.us.csr
// mehrere Domains in einem Zertikat
// (www.meinedomain.de, meinedomain.de, foobar.meinedomain.de..)
# openssl req -new -sha256 \
-key subdomain.bau-ha.us.key \
-subj "/" -reqexts SAN \
-config <(cat /etc/ssl/openssl.cnf } \
<(printf "[SAN]\nsubjectAltName=DNS:subdomain.bau-ha.us,DNS:www.subdomain.de")) \
> subdomain.bau-ha.us.csr
Challenges Verzeichnis in nginx Konfiguration einbinden
muss laufen für acme.sh und acme_tiny
# /etc/nginx/sites-available/subdomain.bau-ha.us
server {
listen 80;
server_name subdomain.bau-ha.us foobarbaz.subdomain.bau-ha.us;
location /.well-known/acme-challenge/ {
alias /var/www/challenges/;
try_files $uri =404;
}
// optional redirect https-only
location / {
return 301 https://$host$request_uri;
}
}
acme_tiny: Zertifikat von Let's Encrypt unterschreiben lassen.
Per Script
# /etc/letsencrypt/ssl/renew.sh subdomain.bau-ha.us
Manuell
# acme_tiny --account-key ./account.key \
--csr ./subdomain.bau-ha.us.csr \
--acme-dir /var/www/challenges/ \
> ./subdomain.bau-ha.us.crt
// Let's Encrypt Intermediate Zertifikat hinzufügen
# wget -q -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > /tmp/intermediate.pem
# cat subdomain.bau-ha.us.crt /tmp/intermediate.pem > subdomain.bau-ha.us.chained.pem
nginx
Jetzt kann man die Zertifikate in den nginx Virtualhost einbinden:
server {
listen 443 ssl http2;
server_name subdomain.bau-ha.us;
server_tokens off;
ssl on;
# ssl magic
# acme_tiny
ssl_certificate /etc/ssl/letsencrypt/subdomain.bau-ha.us.chained.pem;
ssl_certificate_key /etc/ssl/letsencrypt/subdomain.bau-ha.us.key;
# acme.sh
ssl_certificate /root/.acme.sh/subdomain.bau-ha.us/fullchain.cer;
ssl_certificate_key /root/.acme.sh/subdomain.bau-ha.us/subdomain.bau-ha.us.key;
ssl_trusted_certificate /root/.acme.sh/subdomain.bau-ha.us/ca.cer;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
...
}
Erneuerung mit cron
Jetzt noch die crontab
für das monatliche erneuern der Zertifikate:
0 0 1 * * /etc/ssl/letsencrypt/renew.sh kulturtragwerk.de 2>> /var/log/acme_tiny.log
Testen kann man mit nginx -t
und nginx neustarten mit nginx -s
.
Datenbank
PostgreSQL
Wir haben PostgreSQL 9.6 am laufen.
Neue Datenbank anlegen:
# sudo -u postgres -i
$ psql -U postgres
CREATE ROLE myuser LOGIN password 'secret';
CREATE DATABASE mydatabase ENCODING 'UTF8' OWNER myuser;
MySQL
Neue Datenbank anlegen:
$ mysql -u root -p
CREATE DATABASE database;
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'secret';
GRANT ALL PRIVILEGES ON database.* TO newuser@localhost;
PHP
Wir haben PHP5.6 und PHP7.1 via php-fpm. Am einfachsten ist es ein einen neuen Pool mit dem Namen des neuen Users anzulegen.
# cd /etc/php/7.1/fpm/pool.d
; /etc/php/7.1/fpm/pool.d/newuser.conf
[newuser]
user = newuser
group = newuser
listen = /run/php/php7.1-fpm-newuser.sock
listen.owner = www-data
listen.group = www-data
; kann man anpassen, ondemand spart ram, wenn wenig genutzt, sonst dynamic
pm = ondemand
pm.max_children = 2
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 1
; idle timeout für ondemand
pm.process_idle_timeout = 10s;
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
PHP neustarten kann man mit
# systemctl restart php7.1-fpm
Status mit letzten Logmeldungen:
# systemctl status php7.1-fpm
Jetzt kann man im nginx via FastCGI PHP nutzen:
location ^~ /~newuser {
alias /home/newuser/public_html;
location ~ \.php(?|$) {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass unix:/run/php/php7.1-fpm-newuser.sock;
}
}
Python/Ruby/CGI etc.pp...
Klappt vermutlich mit uWSGI. Hier ein Beispiel
uWSGI Apps kann man in /etc/uwsgi/apps-available/
konfigurieren und nach /etc/uwsgi/apps-enabled/
symlinken.
Ein Beispiel für eine Ruby App:
[uwsgi]
plugins = rack
uid = 33
gid = 33
rack = /var/www/redmine/config.ru
post-buffering = 4096
env = RAILS_ENV=production
processes = 4
disable-logging = true
ignore-sigpipe = true
ignore-write-errors = true
logto = /dev/null
Python 2.6 mit Django und virtualenv
:
[uwsgi]
plugins = python26
pythonpath = /home/user/app-env
home = /home/user/app-env
mount = /appurl=/home/user/app/deploy/app.wsgi
virtualenv = /home/user/app-env
processes = 4
Mailman via CGI:
[uwsgi]
plugins = cgi
threads = 5
cgi = /mailman=/usr/lib/cgi-bin/mailman/
cgi-index = listinfo
disable-logging
ignore-sigpipe
ignore-write-errors
buffer-size = 8192
chdir = /
uid = nobody
gid = list
Proxy
...