Installation via Docker
Beschreibung
Kimai via Docker mit https via Letsencrypt.
Installation
Vorbereitung
Sollte Apparmor enabled sein, wie das bei hetzner der Fall ist dann noch eben die Apparmor Pakete installieren
apt-get install apparmor apparmor-utils
Als erstes erstellen wir unsere Verzeichnisse
mkdir -p /root/kimai/mariadb
mkdir -p /root/kimai/data
Nun erstellen wir im Verzeichnis /root/kimai eine neue Datei namens .env
nano /root/kimai/.env
Inhalt:
# MySQL Credentials
MYSQL_ROOT_PASSWORD=12345678
MYSQL_USER=kimai
MYSQL_PASSWORD=1234567890
MYSQL_DATABASE=kimai
# Volume directories
MARIADB_VOLUME_DIR=/root/kimai/mariadb
DATA_VOLUME_DIR=/root/kimai/data
# Domain and email for Let's Encrypt
DOMAIN_NAME=ihredomain.de
LETSENCRYPT_EMAIL=ihre-email@beispiel.de
Docker-compose Datei erstellen
nano /root/kimai/docker-compose.yml
Inhalt
version: '3.3'
services:
mariadb:
image: mariadb:latest
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
volumes:
- ${MARIADB_VOLUME_DIR}:/var/lib/mysql
kimai:
image: kimai/kimai2:apache
restart: unless-stopped
environment:
- DATABASE_URL=mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mariadb/${MYSQL_DATABASE}
volumes:
- ${DATA_VOLUME_DIR}:/opt/kimai/var
webserver:
image: nginx:alpine
restart: unless-stopped
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ${DATA_VOLUME_DIR}:/opt/kimai/var
- ./certbot-etc:/etc/letsencrypt
- ./certbot-www:/var/www/certbot
- ./certbot-log:/var/log/letsencrypt
- ./nginx-log:/var/log/nginx
ports:
- "80:80"
- "443:443"
certbot:
image: certbot/certbot
volumes:
- ./certbot-etc:/etc/letsencrypt
- ./certbot-www:/var/www/certbot
- ./certbot-log:/var/log/letsencrypt
entrypoint: '/bin/sh -c'
volumes:
mariadb_data:
kimai_data:
certbot-etc:
certbot-www:
Nun sicher stellen das die ports 80 und 443 auch über die Domain auf den Server ereichbar sind.
hier ein kleines script das auf den port 80 lauscht um dies zu testen
nano /root/kimai/testeweb.sh
Inhalt
#!/bin/bash
# Funktion, die aufgerufen wird, wenn das Skript ein SIGINT-Signal (Ctrl+C) empfängt
cleanup() {
echo "Server wird beendet..."
exit 0
}
# Trap für das SIGINT-Signal einrichten
trap cleanup SIGINT
# Endlosschleife für den Server
while true; do
# Listen on port 80
{ echo -ne "HTTP/1.1 200 OK\r\nContent-Length: $(echo -n "Hello, World!" | wc -c)\r\n\r\nHello, World!"; } | nc -l -p 80 -q 1
done
Danach ausführbar machen
chmod +x /root/kimai/testeweb.sh
nun das Script starten, kann mit strg+c wieder abgebrochen werden.
Nun kann getestet werden ob Firewall/Portforwarding richtig funktioniert, idem in einem Webbrowser die public ip aufegrufen wird.
Es muss eine hello World Seite zurück gegben werden.
Nun das Init shell script erstellen was die cert Verzeichnisse und die nginx.conf erstellt.
Das programm holt sich den cert Pfad aus der docker-compose datei. Denn der certbot wird mit docker compose im Shellscript gestartet.
jetzt muss nur noch sichergestellt werden das der Domainname auf die ip zeigt
nano /root/kimai/setup.sh
docker-compose run --rm --entrypoint "" certbot certbot certonly --dry-run --webroot --webroot-path=/var/www/certbot \
--email ${LETSENCRYPT_EMAIL} --agree-tos --no-eff-email \
--domain ${DOMAIN_NAME} --rsa-key-size 4096
Inhalt
#!/bin/bash
# Laden der Umgebungsvariablen aus der .env-Datei
if [ -f .env ]; then
export $(grep -v '^#' .env | xargs)
else
echo ".env-Datei nicht gefunden!"
exit 1
fi
# Überprüfen, ob DOMAIN_NAME und LETSENCRYPT_EMAIL gesetzt sind
if [ -z "$DOMAIN_NAME" ] || [ -z "$LETSENCRYPT_EMAIL" ]; then
echo "DOMAIN_NAME und/oder LETSENCRYPT_EMAIL sind in der .env-Datei nicht gesetzt!"
exit 1
fi
# Erstellen der benötigten Verzeichnisse
mkdir -p ./certbot-etc
mkdir -p ./certbot-www
mkdir -p ./certbot-log
mkdir -p ./nginx-log
# Erstellen der Nginx-Konfigurationsdatei für den ersten Lauf (ohne SSL)
cat << EOF > ./nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
server {
listen 80;
server_name ${DOMAIN_NAME};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
try_files \$uri =404;
}
}
}
EOF
# Starten des Webserver-Containers (erster Lauf ohne SSL)
echo "Starte Webserver-Container..."
docker-compose down
docker-compose up -d webserver
# Warten, um sicherzustellen, dass Nginx vollständig gestartet ist
echo "Warte auf Webserver..."
sleep 5
# Ausführen des Certbot für den ersten Lauf
echo "Starte Certbot..."
docker-compose run --rm --entrypoint "" certbot certbot certonly --webroot --webroot-path=/var/www/certbot \
--email ${LETSENCRYPT_EMAIL} --agree-tos --no-eff-email \
--domain ${DOMAIN_NAME} --rsa-key-size 4096
# Aktualisieren Sie die Nginx-Konfigurationsdatei, um SSL zu aktivieren
cat << EOF > ./nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
server {
listen 80;
server_name ${DOMAIN_NAME};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
try_files \$uri =404;
}
location / {
return 301 https://\$host\$request_uri;
}
}
server {
listen 443 ssl;
server_name ${DOMAIN_NAME};
ssl_certificate /etc/letsencrypt/live/${DOMAIN_NAME}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN_NAME}/privkey.pem;
location / {
proxy_pass http://kimai:8001;
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;
client_max_body_size 100M;
}
}
}
EOF
# Starten Sie den Webserver-Container neu, um die aktualisierte Konfiguration zu verwenden
echo "Starte Webserver-Container neu..."
docker-compose down
docker-compose up -d webserver
echo "Setup abgeschlossen. Bitte überprüfen und anpassen Sie die nginx.conf entsprechend."
Das script ausführbar machen
chmod +x /root/kimai/setup.sh
Docker installieren, env anpassen Webcheck und Container starten
apt install docker.io docker-compose
Nun die .env Datei wenn nicht schon geschenen, an die eigenen Bedüfnisse anpassen.
Dann das setup.sh script ausführen.
./setup.sh
Container Starten
Ins kimai Verzeichnis gehen
cd /root/kimai
Nun
docker-compose up
ausführen, dort gibts dann die consolen ausgabe.
Wenn alles läuft und initialisiert ist den Container mit
docker-compose down
wieder stoppen und dann als Daemon mit
docker-compose up -d
wieder starten
Benutzer anlegen
Die Rollen
| Role name | Description |
|---|---|
| User | Normal user can track their working times, see basic reports and change their own preferences. Technical name: ROLE_USER |
| Teamlead | Manages teams with permissions for invoices and access to all team timesheets. Technical name: ROLE_TEAMLEAD |
| Administrator | Can manage all content and timesheet related data, but lack user administration and system privileges. Technical name: ROLE_ADMIN |
| System-Admin | Has permissions to manage everything in Kimai, from content to timesheets to users, plugins and system configurations. Technical name: ROLE_SUPER_ADMIN |
die container id mit docker ps herausfinden
docker exec -ti <containerid> \
/opt/kimai/bin/console kimai:user:create <username> <emailadresse> ROLE_SUPER_ADMIN
Beispiel:
docker exec -ti 32da986c57c2 \
/opt/kimai/bin/console kimai:user:create admin admin@example.com ROLE_SUPER_ADMIN
Dann kann ein Kennwort vergeben werden. Muss mindestens 8 Zeichen haben
Benutzer Passwort ändern
die container id mit docker ps herausfinden
docker exec -ti <containerid> \
/opt/kimai/bin/console kimai:user:password <username>
Beispiel:
docker exec -ti 32da986c57c2 \
/opt/kimai/bin/console kimai:user:password admin
Dann kann ein neues Kennwort vergeben werden. Muss mindestens 8 Zeichen haben
Autostart
Ein script das im Verzeichnis liegen muss wo die .env und die docker-compose.yml liegen
nano /root/kimai/createrenewservice.sh
Inhalt
#!/bin/bash
# Ermitteln des Verzeichnisses, in dem dieses Skript liegt
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
# Pfade zu .env und docker-compose.yml Dateien
ENV_PATH="$SCRIPT_DIR/.env"
DOCKER_COMPOSE_PATH="$SCRIPT_DIR/docker-compose.yml"
# Lesen der .env-Datei
if [ -f "$ENV_PATH" ]; then
export $(grep -v '^#' "$ENV_PATH" | xargs)
else
echo "$ENV_PATH nicht gefunden!"
exit 1
fi
# Erstellen der systemd-Service-Datei
cat << EOF |tee /etc/systemd/system/certbot-renew.service
[Unit]
Description=Certbot Renewal
[Service]
Type=oneshot
ExecStart=/usr/bin/docker-compose -f $DOCKER_COMPOSE_PATH run --rm --entrypoint "" certbot certbot renew --quiet --deploy-hook "docker-compose exec webserver nginx -s reload"
Environment=LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
Environment=DOMAIN_NAME=${DOMAIN_NAME}
[Install]
WantedBy=multi-user.target
EOF
# Erstellen der systemd-Timer-Datei
cat << EOF | tee /etc/systemd/system/certbot-renew.timer
[Unit]
Description=Timer for Certbot Renewal
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Aktivieren und Starten des systemd-Dienstes und Timers
systemctl enable certbot-renew.service
systemctl start certbot-renew.service
systemctl enable certbot-renew.timer
systemctl start certbot-renew.timer
echo "Certbot systemd Dienst und Timer wurden eingerichtet."
Danach das script, ausführbar machen
chmod +x createrenewservice.sh
Nun ausführen
./createrenewservice.sh
Nun den Dienst testen
systemctl start certbot-renew.service
Status des Timers überpüfen
systemctl list-timers
Ausgabe
NEXT LEFT LAST PASSED UNIT ACTIVATES
Wed 2024-01-03 18:33:24 CET 2h 56min left Wed 2024-01-03 09:08:28 CET 6h ago apt-daily.timer apt-daily.se>
Thu 2024-01-04 00:00:00 CET 8h left n/a n/a certbot-renew.timer certbot-rene>
Thu 2024-01-04 00:00:00 CET 8h left Wed 2024-01-03 08:12:38 CET 7h ago logrotate.timer logrotate.se>
Thu 2024-01-04 00:00:00 CET 8h left Wed 2024-01-03 08:12:38 CET 7h ago man-db.timer man-db.servi>
Thu 2024-01-04 06:32:46 CET 14h left Wed 2024-01-03 08:31:44 CET 7h ago apt-daily-upgrade.timer apt-daily-up>
Thu 2024-01-04 08:30:32 CET 16h left Wed 2024-01-03 08:30:32 CET 7h ago systemd-tmpfiles-clean.timer systemd-tmpf>
Sun 2024-01-07 03:10:39 CET 3 days left Wed 2024-01-03 08:13:10 CET 7h ago e2scrub_all.timer e2scrub_all.>
Mon 2024-01-08 00:14:39 CET 4 days left Wed 2024-01-03 09:08:29 CET 6h ago fstrim.timer fstrim.servi>
...
Thu 2024-01-04 00:00:00 CET 8h left n/a n/a certbot-renew.timer
...
noch 8 Stunden verbleibend... Timer ist aktiv
Überpüfen on das Zertifikat erneuert wurde.