Compare commits

...

2 commits

3 changed files with 312 additions and 40 deletions

View file

@ -5,6 +5,7 @@ Welcome to the Likwid documentation. This guide covers everything you need to kn
## Documentation Structure ## Documentation Structure
### For Users ### For Users
- [Getting Started](user/getting-started.md) - First steps with Likwid - [Getting Started](user/getting-started.md) - First steps with Likwid
- [Communities](user/communities.md) - Creating and participating in communities - [Communities](user/communities.md) - Creating and participating in communities
- [Proposals & Voting](user/voting.md) - Understanding the decision-making process - [Proposals & Voting](user/voting.md) - Understanding the decision-making process
@ -12,14 +13,17 @@ Welcome to the Likwid documentation. This guide covers everything you need to kn
- [Account Settings](user/settings.md) - Managing your account - [Account Settings](user/settings.md) - Managing your account
### For System Administrators ### For System Administrators
- [Installation](admin/installation.md) - Deploying Likwid - [Installation](admin/installation.md) - Deploying Likwid
- [Configuration](admin/configuration.md) - Server and instance settings - [Configuration](admin/configuration.md) - Server and instance settings
- [Database](admin/database.md) - PostgreSQL setup and maintenance - [Database](admin/database.md) - PostgreSQL setup and maintenance
- [Plugins](admin/plugins.md) - Managing plugins and voting methods - [Plugins](admin/plugins.md) - Managing plugins and voting methods
- [Security](admin/security.md) - Security best practices - [Security](admin/security.md) - Security best practices
- [Backup & Recovery](admin/backup.md) - Data protection - [Backup & Recovery](admin/backup.md) - Data protection
- [openSUSE Operator Kit](admin/opensuse-operator-kit.md) - openSUSE Leap deployment and operations (container-first)
### Reference ### Reference
- [API Reference](reference/api.md) - REST API documentation - [API Reference](reference/api.md) - REST API documentation
- [Voting Methods](reference/voting-methods.md) - Detailed voting algorithm explanations - [Voting Methods](reference/voting-methods.md) - Detailed voting algorithm explanations
- [Glossary](reference/glossary.md) - Terms and definitions - [Glossary](reference/glossary.md) - Terms and definitions

View file

@ -5,7 +5,7 @@ Protecting your Likwid data.
## What to Backup ## What to Backup
| Component | Location | Priority | | Component | Location | Priority |
|-----------|----------|----------| | ----------- | -------- | -------- |
| PostgreSQL database | Database server | Critical | | PostgreSQL database | Database server | Critical |
| Uploaded files | `/uploads` (if configured) | High | | Uploaded files | `/uploads` (if configured) | High |
| Configuration | `.env` files | High | | Configuration | `.env` files | High |
@ -13,61 +13,147 @@ Protecting your Likwid data.
## Database Backup ## Database Backup
### Manual Backup Likwid's recommended backup mechanism is a logical PostgreSQL dump (via `pg_dump`).
### Where backups live (recommended)
Store backups under the deploy user, next to the repo:
```bash ```bash
# Full backup mkdir -p ~/likwid/backups
pg_dump -h localhost -U likwid -F c likwid_prod > backup_$(date +%Y%m%d).dump
# SQL format (readable)
pg_dump -h localhost -U likwid likwid_prod > backup_$(date +%Y%m%d).sql
``` ```
### Automated Backup Script Retention guidance:
- Keep at least 7 daily backups.
- For production instances, also keep at least 4 weekly backups.
- Keep at least one offsite copy.
### Backup now (containerized, recommended)
#### Production compose (`compose/production.yml`)
The production database container is named `likwid-prod-db`.
```bash ```bash
#!/bin/bash ts=$(date +%Y%m%d_%H%M%S)
# /etc/cron.daily/likwid-backup podman exec -t likwid-prod-db pg_dump -U likwid -F c -d likwid_prod > ~/likwid/backups/likwid_prod_${ts}.dump
BACKUP_DIR="/var/backups/likwid"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
# Create backup
pg_dump -h localhost -U likwid -F c likwid_prod > "$BACKUP_DIR/likwid_$DATE.dump"
# Compress
gzip "$BACKUP_DIR/likwid_$DATE.dump"
# Remove old backups
find "$BACKUP_DIR" -name "*.dump.gz" -mtime +$RETENTION_DAYS -delete
# Optional: sync to remote storage
# aws s3 cp "$BACKUP_DIR/likwid_$DATE.dump.gz" s3://bucket/backups/
``` ```
### Containerized Backup #### Demo compose (`compose/demo.yml`)
The demo database container is named `likwid-demo-db`.
```bash ```bash
# If using podman compose ts=$(date +%Y%m%d_%H%M%S)
podman exec likwid-prod-db pg_dump -U likwid likwid_prod > backup.sql podman exec -t likwid-demo-db pg_dump -U likwid_demo -F c -d likwid_demo > ~/likwid/backups/likwid_demo_${ts}.dump
``` ```
#### Notes
- The `-F c` format is recommended because it is compact and supports `pg_restore --clean`.
- If you are using a shell that does not handle binary stdout redirection well, write the dump inside the container and use `podman cp`.
## Recovery ## Recovery
### Full Restore ### Restore into a fresh environment (containerized)
```bash This procedure is designed to work for a brand new server (or a clean slate on the same server).
# Drop and recreate database
psql -h localhost -U likwid -d postgres -c "DROP DATABASE IF EXISTS likwid_prod;"
psql -h localhost -U likwid -d postgres -c "CREATE DATABASE likwid_prod OWNER likwid;"
# Restore from dump 1. Ensure you have backups of:
pg_restore -h localhost -U likwid -d likwid_prod backup.dump
# Or from SQL - `compose/.env.production` (or `compose/.env.demo`)
psql -h localhost -U likwid likwid_prod < backup.sql - Reverse proxy config
``` - The database dump file (`*.dump`)
1. If you are restoring over an existing instance, stop the stack.
Production:
```bash
cd ~/likwid
podman compose --env-file compose/.env.production -f compose/production.yml down
```
Demo:
```bash
cd ~/likwid
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml down
```
1. If you need an empty database, remove the database volume (destructive).
Production (removes the `likwid_prod_data` volume):
```bash
cd ~/likwid
podman compose --env-file compose/.env.production -f compose/production.yml down -v
```
Demo (removes the `likwid_demo_data` volume):
```bash
cd ~/likwid
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml down -v
```
1. Start only the database container so Postgres recreates the database.
Production:
```bash
cd ~/likwid
podman compose --env-file compose/.env.production -f compose/production.yml up -d postgres
```
Demo:
```bash
cd ~/likwid
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml up -d postgres
```
1. Restore from the dump:
- Production restore:
```bash
podman exec -i likwid-prod-db pg_restore -U likwid -d likwid_prod --clean --if-exists < /path/to/likwid_prod_YYYYMMDD_HHMMSS.dump
```
- Demo restore:
```bash
podman exec -i likwid-demo-db pg_restore -U likwid_demo -d likwid_demo --clean --if-exists < /path/to/likwid_demo_YYYYMMDD_HHMMSS.dump
```
1. Verify the restore:
```bash
podman exec -t likwid-prod-db psql -U likwid -d likwid_prod -c "SELECT now();"
```
1. Start the full stack again (backend + frontend):
Production:
```bash
cd ~/likwid
podman compose --env-file compose/.env.production -f compose/production.yml up -d
```
Demo:
```bash
cd ~/likwid
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml up -d
```
### Restore notes
- `pg_restore --clean --if-exists` drops existing objects before recreating them.
- If you are restoring between different versions, run the matching app version first, then upgrade normally.
### Point-in-Time Recovery ### Point-in-Time Recovery
@ -91,17 +177,19 @@ The demo instance can be reset to initial state:
./scripts/demo-reset.sh ./scripts/demo-reset.sh
``` ```
This removes all demo data by recreating the demo database volume; on startup the backend runs core migrations and demo seed migrations to restore the initial demo dataset. This is destructive and removes all demo data by recreating the demo database volume; on startup the backend runs core migrations and demo seed migrations to restore the initial demo dataset. This is not a backup mechanism.
## Disaster Recovery Plan ## Disaster Recovery Plan
### Preparation ### Preparation
1. Document backup procedures 1. Document backup procedures
2. Test restores regularly (monthly) 2. Test restores regularly (monthly)
3. Keep offsite backup copies 3. Keep offsite backup copies
4. Document recovery steps 4. Document recovery steps
### Recovery Steps ### Recovery Steps
1. Provision new server if needed 1. Provision new server if needed
2. Install Likwid dependencies 2. Install Likwid dependencies
3. Restore database from backup 3. Restore database from backup
@ -111,14 +199,17 @@ This removes all demo data by recreating the demo database volume; on startup th
7. Update DNS if server changed 7. Update DNS if server changed
### Recovery Time Objective (RTO) ### Recovery Time Objective (RTO)
Target: 4 hours for full recovery Target: 4 hours for full recovery
### Recovery Point Objective (RPO) ### Recovery Point Objective (RPO)
Target: 24 hours of data loss maximum (with daily backups) Target: 24 hours of data loss maximum (with daily backups)
## Testing Backups ## Testing Backups
Monthly backup test procedure: Monthly backup test procedure:
1. Create test database 1. Create test database
2. Restore backup to test database 2. Restore backup to test database
3. Run verification queries 3. Run verification queries

View file

@ -0,0 +1,177 @@
# openSUSE Operator Kit (container-first)
This guide describes a practical, operator-first way to run Likwid on openSUSE Leap using Podman (rootless) and a reverse proxy that is already present.
## Assumptions
- You have an SSH-accessible server running openSUSE Leap.
- You run Likwid as a dedicated non-root user (recommended: `deploy`).
- A reverse proxy (Caddy/nginx) terminates TLS and forwards:
- `/` to the frontend
- `/api` to the backend
- You operate via `podman compose`.
## Recommended directory layout
Use a predictable directory layout under the `deploy` user:
- `~/likwid/` (git checkout)
- `~/likwid/compose/.env.production` (production env)
- `~/likwid/compose/.env.demo` (demo env)
- `~/likwid/backups/` (operator-managed backups)
## Install required packages (openSUSE)
Install Podman and Git:
```bash
sudo zypper in -y podman git
```
Verify `podman compose` is available:
```bash
podman compose version
```
If your Podman build does not provide `podman compose`, install the compose integration package available for your openSUSE release.
## Initial bootstrap (production)
1. Clone the repository as the `deploy` user:
```bash
git clone https://codeberg.org/likwid/likwid.git ~/likwid
```
2. Create the production env file:
```bash
cp ~/likwid/compose/.env.production.example ~/likwid/compose/.env.production
```
3. Edit `~/likwid/compose/.env.production`:
- `POSTGRES_PASSWORD`
- `JWT_SECRET`
- `API_BASE` (should be your public URL, e.g. `https://your.domain`)
4. Start services:
```bash
cd ~/likwid
podman compose --env-file compose/.env.production -f compose/production.yml up -d --build
```
5. Create the first admin and complete setup:
- Register the first user at `/register` (first user becomes platform admin)
- Complete `/setup`
## Demo deployment on the VPS
If you operate the public demo style deployment:
```bash
cd ~/likwid
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml up -d --build
```
Health check (backend):
```bash
curl -fsS http://127.0.0.1:3001/health
```
## Upgrade procedure (safe, repeatable)
Use a fetch + hard reset strategy to keep the server in a known state:
```bash
cd ~/likwid
git fetch origin
git reset --hard origin/main
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml up -d --build
```
For production deployments, swap the compose files/env file accordingly.
## Rollback to a known commit
If an upgrade fails, roll back to a previously known-good commit:
```bash
cd ~/likwid
git fetch origin
git reset --hard <KNOWN_GOOD_COMMIT>
podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml up -d --build
```
## Log inspection
Container logs:
```bash
podman logs -f likwid-demo-backend
podman logs -f likwid-demo-frontend
podman logs -f likwid-demo-db
```
Container status:
```bash
podman ps
```
## Firewall and port exposure
- Prefer binding backend/frontend ports to `127.0.0.1` and letting your reverse proxy access them locally.
- Publicly expose only `80/tcp` and `443/tcp`.
- If your compose file binds services on `0.0.0.0`, restrict access via firewall rules.
## Start services on boot (systemd user service)
Podman is most reliable on openSUSE when managed as a rootless user service.
1. Enable lingering for the `deploy` user so services can run without an active SSH session:
```bash
sudo loginctl enable-linger deploy
```
2. Create a systemd user unit:
- File: `~/.config/systemd/user/likwid-demo.service`
```ini
[Unit]
Description=Likwid demo (podman compose)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=%h/likwid
ExecStart=/usr/bin/podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml up -d --build
ExecStop=/usr/bin/podman compose --env-file compose/.env.demo -f compose/demo.yml -f compose/demo.vps.override.yml down
TimeoutStartSec=0
[Install]
WantedBy=default.target
```
3. Enable and start it:
```bash
systemctl --user daemon-reload
systemctl --user enable --now likwid-demo.service
```
4. Inspect service logs:
```bash
journalctl --user -u likwid-demo.service -f
```
For production, create a separate unit (for example `likwid-prod.service`) with the production env file and compose file.