# VPS Server-Dokumentation

> Letzte Aktualisierung: Mai 2026  
> Zweck: Vollständige Beschreibung der Server-Infrastruktur für eine Neuaufsetzen falls nötig.

---

## Hosting & Hardware

| Eigenschaft  | Wert                                      |
|--------------|-------------------------------------------|
| Anbieter     | 1984 Hosting (1984.is), Reykjavik, Island |
| VPS-Name     | vpshoxc2sc                                |
| IP           | `195.246.231.210`                         |
| DNS PTR      | vps-195-246-231-210.1984.is               |
| RAM          | 2048 MB (Upgrade Mai 2026)                |
| CPU          | 1 vCore                                   |
| Disk         | 50 GB SSD (Upgrade Mai 2026)              |
| Transfer     | 1 TB/Monat                                |

---

## Betriebssystem

| Eigenschaft | Wert                        |
|-------------|-----------------------------|
| OS          | Debian GNU/Linux 12 (Bookworm) |
| Kernel      | 6.1.0-30-amd64              |

---

## Installierte System-Software

| Paket / Dienst | Version     | Installationsweg | Systemd-Service     |
|----------------|-------------|------------------|---------------------|
| Docker CE      | 29.5.0      | apt (Docker repo) | `docker.service`   |
| Docker Compose | v5.1.3      | docker-compose-plugin (apt) | –          |
| Caddy          | v2.11.3     | apt (caddy repo)  | `caddy.service`    |
| OpenSSH Server | Debian-Standard | apt          | `ssh.service`      |
| cron           | Debian-Standard | apt          | `cron.service`     |
| rsyslog        | Debian-Standard | apt          | `rsyslog.service`  |

### Docker installieren (bei Neuaufsetzen)

```bash
# Docker GPG Key & Repo
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable" \
  > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
```

### Caddy installieren (bei Neuaufsetzen)

```bash
apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
  | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
  | tee /etc/apt/sources.list.d/caddy-stable.list
apt-get update
apt-get install -y caddy
```

---

## Verzeichnisstruktur

```
/opt/
├── bollwerk/              # Bollwerk App-Stack
│   ├── Dockerfile         # Bollwerk-Server Image
│   ├── docker-compose.yml # App + DB + Backup
│   ├── server.jar         # Aktuelles Server-JAR
│   ├── data/              # App-Datendateien (persistent)
│   └── backup/
│       ├── Dockerfile     # Backup-Container Image
│       └── backup.sh      # Backup-Script (pg_dump + Rotation)
└── mail/
    └── docker-compose.yml # Mail-Stack (Maddy + Snappymail)

/etc/caddy/
└── Caddyfile              # Reverse-Proxy Konfiguration

/etc/letsencrypt/
└── live/mail.bollwerk.online/
    ├── fullchain.pem      # TLS-Zertifikat (Mail)
    └── privkey.pem        # TLS-Privat-Key (Mail)
```

---

## App-Stack: `/opt/bollwerk/`

### docker-compose.yml

```yaml
services:
  db:
    image: postgres:17-alpine
    container_name: bollwerk-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: bollwerk
      POSTGRES_USER: bollwerk
      POSTGRES_PASSWORD: <DB_PASSWORD>
    ports:
      - "127.0.0.1:5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

  bollwerk:
    build: .
    container_name: bollwerk-server
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      - BOLLWERK_JWT_SECRET=<SECRET>
      - BOLLWERK_APP_VERSION_CODE=<versionCode>
      - BOLLWERK_APP_VERSION_NAME=<versionName>
      - BOLLWERK_DB_URL=jdbc:postgresql://db:5432/bollwerk
      - BOLLWERK_DB_USER=bollwerk
      - BOLLWERK_DB_PASSWORD=<DB_PASSWORD>
    volumes:
      - backup_data:/backups:ro
      - ./data:/app/data
    depends_on:
      - db

  backup:
    build: ./backup
    container_name: bollwerk-backup
    restart: unless-stopped
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_DB=bollwerk
      - POSTGRES_USER=bollwerk
      - POSTGRES_PASSWORD=<DB_PASSWORD>
    volumes:
      - backup_data:/backups
    depends_on:
      - db

volumes:
  pgdata:
  backup_data:
```

### Dockerfile (Server)

```dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY server.jar server.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Xmx768m", "-jar", "server.jar"]
```

> **Hinweis:** `-Xmx768m` belässt ~1,2 GB für OS + andere Container. Bei weiterem Upgrade ggf. erhöhen.

### Backup-Container

- **Image-Basis:** Alpine (minimal)
- **Funktion:** Regelmäßiger `pg_dump` der PostgreSQL-Datenbank
- **Deduplizierung:** MD5-Checksumme des Dump-Inhalts (ohne Timestamps) – kein Backup bei unveränderten Daten
- **Rotation:** Älteste `.sql.gz`-Dateien werden gelöscht, sobald `/backups/` 1 GB überschreitet
- **Speicherort:** Docker-Volume `backup_data`, eingebunden in `/backups/`

---

## Mail-Stack: `/opt/mail/`

### docker-compose.yml

```yaml
services:
  maddy:
    image: foxcpp/maddy:0.7
    container_name: maddy
    restart: unless-stopped
    hostname: mail.bollwerk.online
    ports:
      - 25:25       # SMTP (eingehend)
      - 465:465     # SMTPS
      - 587:587     # SMTP Submission
      - 143:143     # IMAP
      - 993:993     # IMAPS
    volumes:
      - maddy_data:/data
      - /etc/letsencrypt/live/mail.bollwerk.online/fullchain.pem:/data/tls/fullchain.pem:ro
      - /etc/letsencrypt/live/mail.bollwerk.online/privkey.pem:/data/tls/privkey.pem:ro
      - /etc/letsencrypt/archive:/etc/letsencrypt/archive:ro
    environment:
      - MADDY_HOSTNAME=mail.bollwerk.online
      - MADDY_DOMAIN=bollwerk.online

  snappymail:
    image: djmaze/snappymail:latest
    container_name: snappymail
    restart: unless-stopped
    ports:
      - 127.0.0.1:8888:8888
    volumes:
      - snappymail_data:/var/lib/snappymail

volumes:
  maddy_data:
  snappymail_data:
```

> **TLS-Zertifikate:** Liegen unter `/etc/letsencrypt/`. Wurden vermutlich per `certbot` oder Caddy ausgestellt. Bei Neuaufsetzen: `certbot certonly --standalone -d mail.bollwerk.online` (während Caddy gestoppt ist).

---

## Reverse Proxy: Caddy

**Konfigurationsdatei:** `/etc/caddy/Caddyfile`

```
bollwerk.online {
    reverse_proxy localhost:8080 {
        header_up X-Forwarded-Proto {scheme}
        header_up X-Forwarded-Host {host}
    }
}

mail.bollwerk.online {
    reverse_proxy localhost:8888 {
        header_up X-Forwarded-Proto {scheme}
        header_up X-Forwarded-Host {host}
    }
}
```

- Caddy übernimmt automatisch TLS via Let's Encrypt für `bollwerk.online` und `mail.bollwerk.online`
- Der Bollwerk-Server ist nur lokal auf Port 8080 gebunden (nicht direkt von außen erreichbar)
- Snappymail-Webmail ist nur lokal auf Port 8888 gebunden

---

## Netzwerk & Ports

| Port | Protokoll | Dienst              | Erreichbarkeit |
|------|-----------|---------------------|----------------|
| 22   | TCP       | SSH                 | Extern         |
| 80   | TCP       | Caddy (HTTP→HTTPS)  | Extern         |
| 443  | TCP       | Caddy (HTTPS)       | Extern         |
| 25   | TCP       | Maddy SMTP          | Extern         |
| 143  | TCP       | Maddy IMAP          | Extern         |
| 465  | TCP       | Maddy SMTPS         | Extern         |
| 587  | TCP       | Maddy Submission    | Extern         |
| 993  | TCP       | Maddy IMAPS         | Extern         |
| 5432 | TCP       | PostgreSQL          | Nur lokal (127.0.0.1) |
| 8080 | TCP       | Bollwerk-Server     | Nur lokal (127.0.0.1) |
| 8888 | TCP       | Snappymail          | Nur lokal (127.0.0.1) |

---

## SSH-Zugang

```bash
ssh root@195.246.231.210
# Key: Ed25519, Fingerprint: SHA256:J/qjVt9r8CqnoshZFQWutau+3KG7JxDzRLHPyX41+gA
```

> **Achtung:** `PasswordAuthentication yes` und `PermitRootLogin yes` sind aktiv. Bei Neuaufsetzen empfohlen: `PasswordAuthentication no` setzen, sobald SSH-Key-Zugang bestätigt ist.

---

## Neuaufsetzen: Schritt-für-Schritt

1. **VPS bestellen** bei 1984.is (Debian 12, min. 2 GB RAM, 50 GB SSD)
2. **SSH-Key hinterlegen** im 1984-Panel oder beim ersten Login
3. **System aktualisieren:** `apt-get update && apt-get upgrade -y`
4. **Docker installieren** (siehe oben)
5. **Caddy installieren** (siehe oben)
6. **Caddyfile anlegen** unter `/etc/caddy/Caddyfile` (Inhalt siehe oben)
7. **Caddy starten:** `systemctl enable --now caddy`
8. **TLS-Zertifikat für Mail holen** (optional, falls Caddy es nicht übernimmt):
   ```bash
   apt-get install -y certbot
   systemctl stop caddy
   certbot certonly --standalone -d mail.bollwerk.online
   systemctl start caddy
   ```
9. **App-Verzeichnis anlegen:**
   ```bash
   mkdir -p /opt/bollwerk/backup /opt/bollwerk/data
   ```
10. **Dateien hochladen:** `Dockerfile`, `docker-compose.yml`, `backup/Dockerfile`, `backup/backup.sh`, `server.jar`
11. **Secrets in `docker-compose.yml` eintragen** (`BOLLWERK_JWT_SECRET`, Passwörter)
12. **App-Stack starten:** `cd /opt/bollwerk && docker compose up -d --build`
13. **Mail-Verzeichnis anlegen:** `mkdir -p /opt/mail`
14. **Mail `docker-compose.yml` hochladen** und starten: `cd /opt/mail && docker compose up -d`
15. **Backup aus altem Server wiederherstellen** (falls vorhanden):
    ```bash
    # .sql.gz aus backup_data-Volume in neuen DB-Container importieren
    gunzip -c backup.sql.gz | docker exec -i bollwerk-db psql -U bollwerk bollwerk
    ```
