# Eternity Project web server A Dockerized publishing service for eternityproject.fi. It provides local accounts, password hashing, authenticated publishing, and owner-only post editing. Content is persisted to SQLite in a named Docker volume. ## Run it 1. Copy `.env.example` to `.env` and replace `SECRET_KEY` with a long random string. 2. Build and start the service: ```sh docker compose up --build -d ``` Open `http://localhost:8000`, create the first account, and publish a field note. The first request initializes the database automatically. ## Accounts and MFA The initial administrator account is `admin` with password `admin`, as requested for first-run access. Sign in, scan the displayed QR code with any iPhone or Android TOTP authenticator, and change this password before exposing the service to the internet. New registrations are held for approval in **Accounts**; accepted users must enroll a TOTP authenticator before they can publish. ### Secure the initial administrator With the Docker service running, rotate the initial password locally. The command prompts for a new password without writing it to a file or command history. It also clears the old MFA binding so that the next administrator sign-in requires a new QR-based authenticator enrollment. ```powershell # Windows PowerShell .\scripts\rotate-admin.ps1 ``` ```sh # Linux, macOS, or any POSIX shell sh ./scripts/rotate-admin.sh ``` After it prints `ADMIN_PASSWORD_ROTATED_MFA_RESET`, sign in as `admin` with the new password, scan the fresh QR code with an authenticator application, and enter its six-digit code to complete enrollment. Store the new password in a password manager. ## Email and password recovery Registration now requires an email address. Members can change their password from the navigation. The sign-in page provides an email-based recovery link; it expires after one hour and can only be used once. Administrators can send the same recovery email to any approved member from **Accounts**. All browser POST forms are protected by server-validated CSRF tokens. Set `PUBLIC_URL` and the `MAIL_*` values in `.env` to send recovery emails. The SMTP account must support STARTTLS on the configured port. Review [TODO.md](TODO.md) before production deployment. ### Configure SMTP delivery 1. Copy `.env.example` to `.env` if it does not exist. 2. Set `PUBLIC_URL=https://eternityproject.fi`. 3. Enter the SMTP host, port, username, password or provider app password, and verified sender address. Use port `587` for STARTTLS. 4. Rebuild the service so Compose applies the values: ```sh docker compose up --build -d ``` 5. Confirm the SMTP connection, TLS handshake, and credentials without sending an email: ```sh python ./scripts/check-smtp.py ``` The command prints `SMTP_CONNECTION_OK` only after the SMTP server accepts the STARTTLS connection and authenticates the configured account. It prints a clear configuration or connection error otherwise and never sends a message. 6. Send a delivery test to an inbox you control: ```sh python ./scripts/send-test-email.py --to you@example.com ``` The command works on Windows, Linux, and macOS. It prints `SMTP_TEST_SENT_TO=
` only after the SMTP server accepts the message. Confirm the message arrives, then use **Forgot your password?** in the application to verify a real reset email and link. The existing PowerShell alternative remains available as `./scripts/test-smtp.ps1 -To you@example.com`. SMTP connection and delivery have been verified for the current deployment environment. ## Automated database backups The portable backup tool creates a consistent snapshot from the running Docker service using SQLite's backup API. It retains the most recent 30 days by default; snapshots are stored in the ignored `backups/` directory. ```sh python ./scripts/backup-database.py python ./scripts/verify-backup.py ./backups/eternity-YYYYMMDDTHHMMSSZ.db ``` The restore verification copies the selected snapshot to a temporary location, checks SQLite integrity, and reports the recovered user and post counts. It never changes the live database. Schedule a daily backup from the project directory. Ensure the scheduler environment provides `SECRET_KEY` for Docker Compose interpolation, or use the same `.env` file used to start the service. ```cron 0 2 * * * cd /srv/docker-ep-blog-web-server && SECRET_KEY="$(grep '^SECRET_KEY=' .env | cut -d= -f2-)" python3 ./scripts/backup-database.py >> backups/backup.log 2>&1 ``` On Windows, create a daily Task Scheduler task with **Start in** set to the project directory and this program/argument pair: ```text Program: python.exe Arguments: .\scripts\backup-database.py ``` Run `python ./scripts/verify-backup.py