- Makefile: build/test/lint/generate/man/install/clean/dist/docker; CGO_ENABLED=1 throughout; VERSION from git describe --tags --always - Dockerfile: multi-stage (golang:1.26-bookworm builder -> debian:bookworm-slim runtime); non-root uid 10001 (mcias), VOLUME /data, EXPOSE 8443/9443; no toolchain in final image - dist/mcias.service: hardened systemd unit (ProtectSystem=strict, ProtectHome, PrivateTmp, NoNewPrivileges, MemoryDenyWriteExecute, CapabilityBoundingSet= empty, EnvironmentFile, LimitNOFILE=65536) - dist/mcias.env.example: passphrase env file template - dist/mcias.conf.example: fully-commented production TOML config - dist/mcias-dev.conf.example: local dev config (/tmp, short expiry) - dist/mcias.conf.docker.example: container config template - dist/install.sh: POSIX sh idempotent installer; creates mcias user/group, installs binaries, /etc/mcias, /var/lib/mcias, systemd unit, man pages; prints post-install instructions - man/man1/mciassrv.1: mdoc synopsis/config/API/signals/files - man/man1/mciasctl.1: mdoc all subcommands/env/examples - man/man1/mciasdb.1: mdoc trust model/safety/all subcommands - man/man1/mciasgrpcctl.1: mdoc gRPC commands/grpcurl example - README.md: user-facing quick-start, first-run setup, build instructions, CLI references, Docker deployment, security notes - .gitignore: added /bin/, dist/mcias_*.tar.gz, man/man1/*.gz
226 lines
6.9 KiB
Bash
226 lines
6.9 KiB
Bash
#!/bin/sh
|
|
# install.sh — MCIAS first-time and upgrade installer
|
|
#
|
|
# Usage: sh dist/install.sh
|
|
#
|
|
# This script must be run as root. It:
|
|
# 1. Creates the mcias system user and group (idempotent).
|
|
# 2. Copies binaries to /usr/local/bin/.
|
|
# 3. Creates /etc/mcias/ and /var/lib/mcias/ with correct permissions.
|
|
# 4. Installs the systemd service unit.
|
|
# 5. Prints post-install instructions.
|
|
#
|
|
# The script does NOT start or enable the service automatically. Review the
|
|
# configuration files and set the master key passphrase before starting.
|
|
#
|
|
# Idempotent: safe to re-run after upgrades. Existing config files are not
|
|
# overwritten; new example files are placed alongside them with a .new suffix
|
|
# so you can review and merge changes.
|
|
#
|
|
# POSIX sh compatible — no bash-isms.
|
|
|
|
set -eu
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Configuration
|
|
# ---------------------------------------------------------------------------
|
|
BIN_DIR="/usr/local/bin"
|
|
CONF_DIR="/etc/mcias"
|
|
DATA_DIR="/var/lib/mcias"
|
|
MAN_DIR="/usr/share/man/man1"
|
|
SYSTEMD_DIR="/etc/systemd/system"
|
|
SERVICE_USER="mcias"
|
|
SERVICE_GROUP="mcias"
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
info() {
|
|
printf '==> %s\n' "$*"
|
|
}
|
|
|
|
warn() {
|
|
printf 'WARNING: %s\n' "$*" >&2
|
|
}
|
|
|
|
die() {
|
|
printf 'ERROR: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
require_root() {
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
die "This script must be run as root."
|
|
fi
|
|
}
|
|
|
|
# install_file SRC DST MODE OWNER
|
|
# Installs SRC to DST. If DST already exists, installs SRC as DST.new
|
|
# so the operator can review changes.
|
|
install_file() {
|
|
src="$1"
|
|
dst="$2"
|
|
mode="$3"
|
|
owner="$4"
|
|
|
|
if [ -e "$dst" ]; then
|
|
info "Existing file found: $dst (installing as $dst.new)"
|
|
install -m "$mode" -o "$owner" "$src" "$dst.new"
|
|
else
|
|
install -m "$mode" -o "$owner" "$src" "$dst"
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Main
|
|
# ---------------------------------------------------------------------------
|
|
require_root
|
|
|
|
# Step 1: Create system user and group.
|
|
info "Creating system user and group: $SERVICE_USER"
|
|
if getent group "$SERVICE_GROUP" > /dev/null 2>&1; then
|
|
info "Group $SERVICE_GROUP already exists — skipping."
|
|
else
|
|
groupadd --system "$SERVICE_GROUP"
|
|
fi
|
|
|
|
if getent passwd "$SERVICE_USER" > /dev/null 2>&1; then
|
|
info "User $SERVICE_USER already exists — skipping."
|
|
else
|
|
useradd \
|
|
--system \
|
|
--gid "$SERVICE_GROUP" \
|
|
--no-create-home \
|
|
--shell /usr/sbin/nologin \
|
|
--comment "MCIAS authentication server" \
|
|
"$SERVICE_USER"
|
|
fi
|
|
|
|
# Step 2: Install binaries.
|
|
info "Installing binaries to $BIN_DIR"
|
|
for bin in mciassrv mciasctl mciasdb mciasgrpcctl; do
|
|
src="$REPO_ROOT/$bin"
|
|
if [ ! -f "$src" ]; then
|
|
# Try bin/ subdirectory (Makefile build output).
|
|
src="$REPO_ROOT/bin/$bin"
|
|
fi
|
|
if [ ! -f "$src" ]; then
|
|
warn "Binary not found: $bin — skipping. Run 'make build' first."
|
|
continue
|
|
fi
|
|
info " Installing $bin"
|
|
install -m 0755 -o root -g root "$src" "$BIN_DIR/$bin"
|
|
done
|
|
|
|
# Step 3: Create configuration directory.
|
|
info "Creating $CONF_DIR"
|
|
install -d -m 0750 -o root -g "$SERVICE_GROUP" "$CONF_DIR"
|
|
|
|
# Install example config files; never overwrite existing configs.
|
|
for f in mcias.conf.example mcias.env.example; do
|
|
src="$SCRIPT_DIR/$f"
|
|
dst="$CONF_DIR/$f"
|
|
if [ -f "$src" ]; then
|
|
install -m 0640 -o root -g "$SERVICE_GROUP" "$src" "$dst" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
# Step 4: Create data directory.
|
|
info "Creating $DATA_DIR"
|
|
install -d -m 0750 -o "$SERVICE_USER" -g "$SERVICE_GROUP" "$DATA_DIR"
|
|
|
|
# Step 5: Install systemd service unit.
|
|
if [ -d "$SYSTEMD_DIR" ]; then
|
|
info "Installing systemd service unit to $SYSTEMD_DIR"
|
|
install -m 0644 -o root -g root "$SCRIPT_DIR/mcias.service" "$SYSTEMD_DIR/mcias.service"
|
|
info "Reloading systemd daemon"
|
|
systemctl daemon-reload 2>/dev/null || warn "systemctl not available; reload manually."
|
|
else
|
|
warn "systemd not found at $SYSTEMD_DIR; skipping service unit installation."
|
|
fi
|
|
|
|
# Step 6: Install man pages.
|
|
if [ -d "$REPO_ROOT/man/man1" ]; then
|
|
install -d -m 0755 -o root -g root "$MAN_DIR"
|
|
info "Installing man pages to $MAN_DIR"
|
|
for page in "$REPO_ROOT/man/man1"/*.1.gz; do
|
|
[ -f "$page" ] || continue
|
|
install -m 0644 -o root -g root "$page" "$MAN_DIR/"
|
|
done
|
|
# Also install uncompressed pages if no gz versions exist.
|
|
for page in "$REPO_ROOT/man/man1"/*.1; do
|
|
[ -f "$page" ] || continue
|
|
gzname="${MAN_DIR}/$(basename "$page").gz"
|
|
if [ ! -f "$gzname" ]; then
|
|
gzip -c "$page" > "$gzname"
|
|
chmod 0644 "$gzname"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Post-install instructions
|
|
# ---------------------------------------------------------------------------
|
|
cat <<EOF
|
|
|
|
==========================================================================
|
|
MCIAS installed successfully.
|
|
==========================================================================
|
|
|
|
Next steps:
|
|
|
|
1. Generate a TLS certificate and key:
|
|
|
|
# Self-signed (development / personal use):
|
|
openssl req -x509 -newkey ed25519 -days 3650 \\
|
|
-keyout /etc/mcias/server.key \\
|
|
-out /etc/mcias/server.crt \\
|
|
-subj "/CN=auth.example.com" \\
|
|
-nodes
|
|
chmod 0640 /etc/mcias/server.key
|
|
chown root:mcias /etc/mcias/server.key
|
|
|
|
2. Copy and edit the configuration file:
|
|
|
|
cp /etc/mcias/mcias.conf.example /etc/mcias/mcias.conf
|
|
\$EDITOR /etc/mcias/mcias.conf
|
|
chmod 0640 /etc/mcias/mcias.conf
|
|
chown root:mcias /etc/mcias/mcias.conf
|
|
|
|
3. Set the master key passphrase:
|
|
|
|
cp /etc/mcias/mcias.env.example /etc/mcias/env
|
|
\$EDITOR /etc/mcias/env # replace the placeholder passphrase
|
|
chmod 0640 /etc/mcias/env
|
|
chown root:mcias /etc/mcias/env
|
|
|
|
IMPORTANT: Back up the passphrase to a secure offline location.
|
|
Losing it means losing access to all encrypted data in the database.
|
|
|
|
4. Enable and start the service:
|
|
|
|
systemctl enable mcias
|
|
systemctl start mcias
|
|
systemctl status mcias
|
|
|
|
5. Create the first admin account using mciasdb (while the server is
|
|
running, or before first start):
|
|
|
|
MCIAS_MASTER_PASSPHRASE=\$(grep MCIAS_MASTER_PASSPHRASE /etc/mcias/env | cut -d= -f2) \\
|
|
mciasdb --config /etc/mcias/mcias.conf account create \\
|
|
--username admin --type human
|
|
|
|
Then set a password:
|
|
MCIAS_MASTER_PASSPHRASE=... mciasdb --config /etc/mcias/mcias.conf \\
|
|
account set-password --id <UUID>
|
|
|
|
And grant the admin role:
|
|
MCIAS_MASTER_PASSPHRASE=... mciasdb --config /etc/mcias/mcias.conf \\
|
|
role grant --id <UUID> --role admin
|
|
|
|
For full documentation, see: man mciassrv
|
|
==========================================================================
|
|
EOF
|