docs: add consolidated installation guide

Add docs/INSTALL.md with two installation paths:
- Option A: Docker Compose (all-in-one with PostgreSQL, MinIO,
  OpenLDAP, and optional nginx)
- Option B: Daemon install (systemd with external services, links to
  setup instructions for PostgreSQL, MinIO, FreeIPA, nginx)

Includes LDAP user/group management instructions, verification steps,
and upgrade procedures for both paths.

Update README.md Quick Start to point to INSTALL.md, add to docs table.
Add redirect banner to DEPLOYMENT.md for first-time users.
Add comments to docker-compose.prod.yaml noting unsupported env vars.
This commit is contained in:
2026-02-12 08:59:10 -06:00
parent 3d9ef9e99e
commit 606316204d
4 changed files with 544 additions and 16 deletions

518
docs/INSTALL.md Normal file
View File

@@ -0,0 +1,518 @@
# Installing Silo
This guide covers two installation methods:
- **[Option A: Docker Compose](#option-a-docker-compose)** — self-contained stack with all services. Recommended for evaluation, small teams, and environments where Docker is the standard.
- **[Option B: Daemon Install](#option-b-daemon-install-systemd--external-services)** — systemd service with external PostgreSQL, MinIO, and optional LDAP/nginx. Recommended for production deployments integrated with existing infrastructure.
Both methods produce the same result: a running Silo server with a web UI, REST API, and authentication.
---
## Table of Contents
- [Prerequisites](#prerequisites)
- [Option A: Docker Compose](#option-a-docker-compose)
- [A.1 Prerequisites](#a1-prerequisites)
- [A.2 Clone the Repository](#a2-clone-the-repository)
- [A.3 Run the Setup Script](#a3-run-the-setup-script)
- [A.4 Start the Stack](#a4-start-the-stack)
- [A.5 Verify the Installation](#a5-verify-the-installation)
- [A.6 LDAP Users and Groups](#a6-ldap-users-and-groups)
- [A.7 Optional: Enable Nginx Reverse Proxy](#a7-optional-enable-nginx-reverse-proxy)
- [A.8 Stopping, Starting, and Upgrading](#a8-stopping-starting-and-upgrading)
- [Option B: Daemon Install (systemd + External Services)](#option-b-daemon-install-systemd--external-services)
- [B.1 Architecture Overview](#b1-architecture-overview)
- [B.2 Prerequisites](#b2-prerequisites)
- [B.3 Set Up External Services](#b3-set-up-external-services)
- [B.4 Prepare the Host](#b4-prepare-the-host)
- [B.5 Configure Credentials](#b5-configure-credentials)
- [B.6 Deploy](#b6-deploy)
- [B.7 Set Up Nginx and TLS](#b7-set-up-nginx-and-tls)
- [B.8 Verify the Installation](#b8-verify-the-installation)
- [B.9 Upgrading](#b9-upgrading)
- [Post-Install Configuration](#post-install-configuration)
- [Further Reading](#further-reading)
---
## Prerequisites
Regardless of which method you choose:
- **Git** to clone the repository
- A machine with at least **2 GB RAM** and **10 GB free disk**
- Network access to pull container images or download Go/Node toolchains
---
## Option A: Docker Compose
A single Docker Compose file runs everything: PostgreSQL, MinIO, OpenLDAP, and Silo. An optional nginx container can be enabled for reverse proxying.
### A.1 Prerequisites
- [Docker Engine](https://docs.docker.com/engine/install/) 24+ with the [Compose plugin](https://docs.docker.com/compose/install/) (v2)
- `openssl` (used by the setup script to generate secrets)
Verify your installation:
```bash
docker --version # Docker Engine 24+
docker compose version # Docker Compose v2+
```
### A.2 Clone the Repository
```bash
git clone https://git.kindred-systems.com/kindred/silo.git
cd silo
```
### A.3 Run the Setup Script
The setup script generates credentials and configuration files:
```bash
./scripts/setup-docker.sh
```
It prompts for:
- Server domain (default: `localhost`)
- PostgreSQL password (auto-generated if you press Enter)
- MinIO credentials (auto-generated)
- OpenLDAP admin password and initial user (auto-generated)
- Silo local admin account (fallback when LDAP is unavailable)
For automated/CI environments, use non-interactive mode:
```bash
./scripts/setup-docker.sh --non-interactive
```
The script writes two files:
- `deployments/.env` — secrets for Docker Compose
- `deployments/config.docker.yaml` — Silo server configuration
### A.4 Start the Stack
```bash
docker compose -f deployments/docker-compose.allinone.yaml up -d
```
Wait for all services to become healthy:
```bash
docker compose -f deployments/docker-compose.allinone.yaml ps
```
You should see `silo-postgres`, `silo-minio`, `silo-openldap`, and `silo-api` all in a healthy state.
View logs:
```bash
# All services
docker compose -f deployments/docker-compose.allinone.yaml logs -f
# Silo only
docker compose -f deployments/docker-compose.allinone.yaml logs -f silo
```
### A.5 Verify the Installation
```bash
# Health check
curl http://localhost:8080/health
# Readiness check (includes database and storage connectivity)
curl http://localhost:8080/ready
```
Open http://localhost:8080 in your browser. Log in with either:
- **LDAP account**: the username and password shown by the setup script (default: `siloadmin`)
- **Local admin**: the local admin credentials shown by the setup script (default: `admin`)
The credentials were printed at the end of the setup script output and are stored in `deployments/.env`.
### A.6 LDAP Users and Groups
The Docker stack includes an OpenLDAP server with three preconfigured groups that map to Silo roles:
| LDAP Group | Silo Role | Access Level |
|------------|-----------|-------------|
| `cn=silo-admins,ou=groups,dc=silo,dc=local` | admin | Full access |
| `cn=silo-users,ou=groups,dc=silo,dc=local` | editor | Create and modify items |
| `cn=silo-viewers,ou=groups,dc=silo,dc=local` | viewer | Read-only |
The initial LDAP user (default: `siloadmin`) is added to `silo-admins`.
**Add a new LDAP user:**
```bash
# From the host (using the exposed port)
ldapadd -x -H ldap://localhost:1389 \
-D "cn=admin,dc=silo,dc=local" \
-w "YOUR_LDAP_ADMIN_PASSWORD" << EOF
dn: cn=jdoe,ou=users,dc=silo,dc=local
objectClass: inetOrgPerson
cn: jdoe
sn: Doe
userPassword: changeme
mail: jdoe@example.com
EOF
```
**Add a user to a group:**
```bash
ldapmodify -x -H ldap://localhost:1389 \
-D "cn=admin,dc=silo,dc=local" \
-w "YOUR_LDAP_ADMIN_PASSWORD" << EOF
dn: cn=silo-users,ou=groups,dc=silo,dc=local
changetype: modify
add: member
member: cn=jdoe,ou=users,dc=silo,dc=local
EOF
```
**List all users:**
```bash
ldapsearch -x -H ldap://localhost:1389 \
-b "ou=users,dc=silo,dc=local" \
-D "cn=admin,dc=silo,dc=local" \
-w "YOUR_LDAP_ADMIN_PASSWORD" "(objectClass=inetOrgPerson)" cn mail memberOf
```
### A.7 Optional: Enable Nginx Reverse Proxy
To place nginx in front of Silo (for TLS termination or to serve on port 80):
```bash
docker compose -f deployments/docker-compose.allinone.yaml --profile nginx up -d
```
By default nginx listens on ports 80 and 443 and proxies to the Silo container. The configuration is at `deployments/nginx/nginx.conf`.
**To enable HTTPS**, edit `deployments/docker-compose.allinone.yaml` and uncomment the TLS certificate volume mounts in the `nginx` service, then uncomment the HTTPS server block in `deployments/nginx/nginx.conf`. See the comments in those files for details.
If you already have your own reverse proxy or load balancer, skip the nginx profile and point your proxy at port 8080.
### A.8 Stopping, Starting, and Upgrading
```bash
# Stop the stack (data is preserved in Docker volumes)
docker compose -f deployments/docker-compose.allinone.yaml down
# Start again
docker compose -f deployments/docker-compose.allinone.yaml up -d
# Stop and delete all data (WARNING: destroys database, files, and LDAP data)
docker compose -f deployments/docker-compose.allinone.yaml down -v
```
**To upgrade to a newer version:**
```bash
cd silo
git pull
docker compose -f deployments/docker-compose.allinone.yaml up -d --build
```
The Silo container is rebuilt from the updated source. Database migrations in `migrations/` are applied automatically on container startup via the PostgreSQL init mechanism.
---
## Option B: Daemon Install (systemd + External Services)
This method runs Silo as a systemd service on a dedicated host, connecting to externally managed PostgreSQL, MinIO, and optionally LDAP services.
### B.1 Architecture Overview
```
┌──────────────────────┐
│ Silo Host │
│ ┌────────────────┐ │
HTTPS (443) ──►│ │ nginx │ │
│ └───────┬────────┘ │
│ │ :8080 │
│ ┌───────▼────────┐ │
│ │ silod │ │
│ │ (API server) │ │
│ └──┬─────────┬───┘ │
└─────┼─────────┼──────┘
│ │
┌───────────▼──┐ ┌───▼──────────────┐
│ PostgreSQL 16│ │ MinIO (S3) │
│ :5432 │ │ :9000 API │
└──────────────┘ │ :9001 Console │
└──────────────────┘
```
### B.2 Prerequisites
- Linux host (Debian/Ubuntu or RHEL/Fedora/AlmaLinux)
- Root or sudo access
- Network access to your PostgreSQL and MinIO servers
The setup script installs Go and other build dependencies automatically.
### B.3 Set Up External Services
#### PostgreSQL 16
Install PostgreSQL and create the Silo database:
- [PostgreSQL downloads](https://www.postgresql.org/download/)
```bash
# After installing PostgreSQL, create the database and user:
sudo -u postgres createuser silo
sudo -u postgres createdb -O silo silo
sudo -u postgres psql -c "ALTER USER silo WITH PASSWORD 'your-password';"
```
Ensure the Silo host can connect (check `pg_hba.conf` on the PostgreSQL server).
Verify:
```bash
psql -h YOUR_PG_HOST -U silo -d silo -c 'SELECT 1'
```
#### MinIO
Install MinIO and create a bucket and service account:
- [MinIO quickstart](https://min.io/docs/minio/linux/index.html)
```bash
# Using the MinIO client (mc):
mc alias set local http://YOUR_MINIO_HOST:9000 minioadmin minioadmin
mc mb local/silo-files
mc admin user add local silouser YOUR_MINIO_SECRET
mc admin policy attach local readwrite --user silouser
```
Verify:
```bash
curl -I http://YOUR_MINIO_HOST:9000/minio/health/live
```
#### LDAP / FreeIPA (Optional)
For LDAP authentication, you need an LDAP server with user and group entries. Options:
- [FreeIPA](https://www.freeipa.org/page/Quick_Start_Guide) — full identity management (recommended for organizations already using it)
- [OpenLDAP](https://www.openldap.org/doc/admin26/) — lightweight LDAP server
Silo needs:
- A base DN (e.g., `dc=example,dc=com`)
- Users under a known OU (e.g., `cn=users,cn=accounts,dc=example,dc=com`)
- Groups that map to Silo roles (`admin`, `editor`, `viewer`)
- The `memberOf` overlay enabled (so user entries have `memberOf` attributes)
See [CONFIGURATION.md — LDAP](CONFIGURATION.md#ldap--freeipa) for the full LDAP configuration reference.
### B.4 Prepare the Host
Run the setup script on the target host:
```bash
# Copy and run the script
scp scripts/setup-host.sh root@YOUR_HOST:/tmp/
ssh root@YOUR_HOST 'bash /tmp/setup-host.sh'
```
Or directly on the host:
```bash
sudo bash scripts/setup-host.sh
```
The script:
1. Installs dependencies (git, Go 1.24)
2. Creates the `silo` system user
3. Creates directories (`/opt/silo`, `/etc/silo`)
4. Clones the repository
5. Creates the environment file template
To override the default service hostnames:
```bash
SILO_DB_HOST=db.example.com SILO_MINIO_HOST=s3.example.com sudo -E bash scripts/setup-host.sh
```
### B.5 Configure Credentials
Edit the environment file with your service credentials:
```bash
sudo nano /etc/silo/silod.env
```
```bash
# Database
SILO_DB_PASSWORD=your-database-password
# MinIO
SILO_MINIO_ACCESS_KEY=silouser
SILO_MINIO_SECRET_KEY=your-minio-secret
# Authentication
SILO_SESSION_SECRET=generate-a-long-random-string
SILO_ADMIN_USERNAME=admin
SILO_ADMIN_PASSWORD=your-admin-password
```
Generate a session secret:
```bash
openssl rand -hex 32
```
Review the server configuration:
```bash
sudo nano /etc/silo/config.yaml
```
Update `database.host`, `storage.endpoint`, `server.base_url`, and authentication settings for your environment. See [CONFIGURATION.md](CONFIGURATION.md) for all options.
### B.6 Deploy
Run the deploy script:
```bash
sudo /opt/silo/src/scripts/deploy.sh
```
The script:
1. Pulls latest code from git
2. Builds the `silod` binary and React frontend
3. Installs files to `/opt/silo` and `/etc/silo`
4. Runs database migrations
5. Installs and starts the systemd service
Deploy options:
```bash
# Skip git pull (use current checkout)
sudo /opt/silo/src/scripts/deploy.sh --no-pull
# Skip build (use existing binary)
sudo /opt/silo/src/scripts/deploy.sh --no-build
# Just restart the service
sudo /opt/silo/src/scripts/deploy.sh --restart-only
# Check service status
sudo /opt/silo/src/scripts/deploy.sh --status
```
To override the target host or database host:
```bash
SILO_DEPLOY_TARGET=silo.example.com SILO_DB_HOST=db.example.com sudo -E scripts/deploy.sh
```
### B.7 Set Up Nginx and TLS
#### With FreeIPA (automated)
If your organization uses FreeIPA, the included script handles nginx setup, IPA enrollment, and certificate issuance:
```bash
sudo /opt/silo/src/scripts/setup-ipa-nginx.sh
```
Override the hostname if needed:
```bash
SILO_HOSTNAME=silo.example.com sudo -E /opt/silo/src/scripts/setup-ipa-nginx.sh
```
The script installs nginx, enrolls the host in FreeIPA, requests a TLS certificate from the IPA CA (auto-renewed by certmonger), and configures nginx as an HTTPS reverse proxy.
#### Manual nginx setup
Install nginx and create a config:
```bash
sudo apt install nginx # or: sudo dnf install nginx
```
Use the template at `deployments/nginx/nginx.conf` as a starting point. Copy it to `/etc/nginx/sites-available/silo`, update the `server_name` and certificate paths, then enable it:
```bash
sudo ln -sf /etc/nginx/sites-available/silo /etc/nginx/sites-enabled/silo
sudo nginx -t
sudo systemctl reload nginx
```
After enabling HTTPS, update `server.base_url` in `/etc/silo/config.yaml` to use `https://` and restart Silo:
```bash
sudo systemctl restart silod
```
### B.8 Verify the Installation
```bash
# Service status
sudo systemctl status silod
# Health check
curl http://localhost:8080/health
# Readiness check
curl http://localhost:8080/ready
# Follow logs
sudo journalctl -u silod -f
```
Open your configured base URL in a browser and log in.
### B.9 Upgrading
```bash
# Pull latest code and redeploy
sudo /opt/silo/src/scripts/deploy.sh
# Or deploy a specific version
cd /opt/silo/src
git fetch --all --tags
git checkout v1.2.3
sudo /opt/silo/src/scripts/deploy.sh --no-pull
```
New database migrations are applied automatically during deployment.
---
## Post-Install Configuration
After a successful installation:
- **Authentication**: Configure LDAP, OIDC, or local auth backends. See [CONFIGURATION.md — Authentication](CONFIGURATION.md#authentication).
- **Schemas**: Part numbering schemas are loaded from YAML files. See the `schemas/` directory and [CONFIGURATION.md — Schemas](CONFIGURATION.md#schemas).
- **Read-only mode**: Toggle write protection at runtime with `kill -USR1 $(pidof silod)` or by setting `server.read_only: true` in the config.
- **Ongoing maintenance**: See [DEPLOYMENT.md](DEPLOYMENT.md) for service management, log viewing, troubleshooting, and the security checklist.
---
## Further Reading
| Document | Description |
|----------|-------------|
| [CONFIGURATION.md](CONFIGURATION.md) | Complete `config.yaml` reference |
| [DEPLOYMENT.md](DEPLOYMENT.md) | Operations guide: maintenance, troubleshooting, security |
| [AUTH.md](AUTH.md) | Authentication system design |
| [AUTH_USER_GUIDE.md](AUTH_USER_GUIDE.md) | User guide for login, tokens, and roles |
| [SPECIFICATION.md](SPECIFICATION.md) | Full design specification and API reference |
| [STATUS.md](STATUS.md) | Implementation status |
| [GAP_ANALYSIS.md](GAP_ANALYSIS.md) | Gap analysis and revision control roadmap |
| [COMPONENT_AUDIT.md](COMPONENT_AUDIT.md) | Component audit tool design |