Appearance
Klassisch (Bare Metal) — Alternative
WARNING
Das ist nicht das Standard-Setup. Verwende für Staging und Production FrankenPHP + Caddy via Docker Compose. Diese Variante ist nur sinnvoll, wenn auf der Maschine zwingend kein Docker laufen darf — z. B. eine geteilte Hosting-Box ohne Container-Erlaubnis. Du verlierst damit Auto-SSL, einheitliche Backup-Pfade und die Stack-Trennung in home/bengel/stacks/.
Setup mit Nginx + PHP-FPM 8.4 + systemd. Forgejo als Binary, Woodpecker in Docker (lässt sich nicht sinnvoll als Binary betreiben). Nuxt-Workloads laufen als systemd-Services.
1. Basis-Software
bash
apt update && apt upgrade -y
apt install -y nginx certbot python3-certbot-nginx \
git curl unzip mariadb-server \
php8.4-fpm php8.4-cli php8.4-mbstring php8.4-xml \
php8.4-curl php8.4-zip php8.4-mysql php8.4-gd \
php8.4-intl php8.4-bcmath php8.4-redis redis-server
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
curl -fsSL https://bun.sh/install | bash
ln -s /root/.bun/bin/bun /usr/local/bin/bun2. Deploy-User
bash
adduser --disabled-password --gecos "" deploy
mkdir -p /home/deploy/.ssh
echo "ssh-ed25519 AAAA..." >> /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh && chmod 600 /home/deploy/.ssh/authorized_keys
mkdir -p /var/www/matev/{admin,cms,b2b,staging,docs,storybook}/{releases,shared}
chown -R deploy:deploy /var/www/matev
echo "deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx, /usr/bin/systemctl restart matev-*" \
>> /etc/sudoers.d/deploy3. Forgejo (als systemd-Service)
bash
wget -O /usr/local/bin/forgejo \
https://codeberg.org/forgejo/forgejo/releases/download/v15.0/forgejo-15.0-linux-amd64
chmod +x /usr/local/bin/forgejo
adduser --system --group --disabled-password --home /var/lib/forgejo forgejo
mkdir -p /var/lib/forgejo/{custom,data,log}
chown -R forgejo:forgejo /var/lib/forgejo
mkdir -p /etc/forgejo
cat > /etc/forgejo/app.ini << 'EOF'
[server]
DOMAIN = git.matev.eu
ROOT_URL = https://git.matev.eu/
HTTP_PORT = 3000
LFS_START_SERVER = true
[database]
DB_TYPE = sqlite3
PATH = /var/lib/forgejo/data/forgejo.db
[service]
DISABLE_REGISTRATION = true
EOF
chown -R forgejo:forgejo /etc/forgejo
cat > /etc/systemd/system/forgejo.service << 'EOF'
[Unit]
Description=Forgejo
After=network.target
[Service]
Type=simple
User=forgejo
Group=forgejo
WorkingDirectory=/var/lib/forgejo
ExecStart=/usr/local/bin/forgejo web -c /etc/forgejo/app.ini
Restart=always
Environment=USER=forgejo HOME=/var/lib/forgejo
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now forgejo
# Admin-User
sudo -u forgejo forgejo admin user create \
--username admin --password admin --email admin@matev.eu --admin \
-c /etc/forgejo/app.ini4. MariaDB
bash
mysql_secure_installation
mysql -u root -p << 'EOF'
CREATE DATABASE matev_admin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE matev_b2b CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'matev'@'localhost' IDENTIFIED BY '<SICHER>';
GRANT ALL ON matev_admin.* TO 'matev'@'localhost';
GRANT ALL ON matev_b2b.* TO 'matev'@'localhost';
FLUSH PRIVILEGES;
EOF5. Nginx-Vhosts
Pro Service ein eigener Vhost. Schema (für admin.matev.eu):
nginx
server {
listen 443 ssl http2;
server_name admin.matev.eu;
ssl_certificate /etc/letsencrypt/live/admin.matev.eu/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/admin.matev.eu/privkey.pem;
root /var/www/matev/admin/current/public;
index index.php;
client_max_body_size 50M;
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* { deny all; }
}Analog für b2b.matev.eu (PHP-FPM), cms.matev.eu (PHP-FPM auf Kirby-Webroot).
Für Nuxt-Workloads (staging.matev.eu, docs.matev.eu) jeweils ein Reverse-Proxy auf den lokalen Port:
nginx
server {
listen 443 ssl http2;
server_name staging.matev.eu;
ssl_certificate /etc/letsencrypt/live/staging.matev.eu/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/staging.matev.eu/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Für git.matev.eu und ci.matev.eu (Forgejo / Woodpecker) gleiches Reverse-Proxy-Schema auf :3000 bzw. :8000.
bash
# Aktivieren
ln -s /etc/nginx/sites-available/* /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx6. SSL
bash
certbot --nginx \
-d admin.matev.eu -d cms.matev.eu -d b2b.matev.eu \
-d staging.matev.eu -d docs.matev.eu -d storybook.matev.eu \
-d analytics.matev.eu -d design.matev.eu -d project.matev.eu \
-d git.matev.eu -d ci.matev.eu7. Nuxt/Bun-Workloads als systemd
/etc/systemd/system/matev-staging.service:
ini
[Unit]
Description=MATEV Staging (Nuxt SSR)
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/var/www/matev/staging/current
EnvironmentFile=/var/www/matev/staging/shared/.env
ExecStart=/usr/local/bin/bun .output/server/index.mjs
Environment=NITRO_PORT=3001 NODE_ENV=production
Restart=always
[Install]
WantedBy=multi-user.targetAnalog für matev-docs auf Port 3002.
bash
systemctl daemon-reload
systemctl enable --now matev-staging matev-docs8. Penpot, Taiga, Matomo
In dieser Variante sind das praktisch nur als Container betreibbar — kein offizielles Bare-Metal-Setup. Wenn Docker auf dem Host gar nicht erlaubt ist, fallen diese Services schlicht weg oder müssen auf einen separaten Host. Das ist der Hauptgrund, warum dieses Setup nur Notlösung ist.
Zugangsdaten
| Service | URL | Login | Passwort |
|---|---|---|---|
| Forgejo | https://git.matev.eu | admin | admin |
| Filament-Admin | https://admin.matev.eu | admin@matev.eu | admin |
DANGER
Alle Standard-Passwörter sofort nach Erstinstallation ändern.