# MCIAS — Metacircular Identity and Access System MCIAS is a self-hosted SSO and IAM service for personal projects. It provides authentication (JWT/Ed25519), account management, TOTP, and Postgres credential storage over a REST API (HTTPS) and a gRPC API (TLS). See [ARCHITECTURE.md](ARCHITECTURE.md) for the technical design and [PROJECT_PLAN.md](PROJECT_PLAN.md) for the implementation roadmap. --- ## Quick Start ### Option A: Install from source **Prerequisites:** Go 1.26+, a C compiler (required by modernc.org/sqlite). ```sh git clone https://git.wntrmute.dev/kyle/mcias cd mcias make build # produces bin/mciassrv, other binaries sudo make install ``` ### Option B: Docker ```sh docker build -t mcias:latest . # or make docker # tags mcias: ``` See [Deploying with Docker](#deploying-with-docker) below. --- ## First-Run Setup ### 1. Generate a TLS certificate **Option A: Using the cert tool** Install the cert tool: ```sh go install github.com/kisom/cert@latest ``` Create a certificate request configuration file: ```sh cat > /tmp/request.yaml << EOF subject: common_name: auth.example.com hosts: - auth.example.com - localhost key: algo: ecdsa size: 521 ca: expiry: 87600h # 10 years EOF ``` Generate the certificate: ```sh cert genkey -a ec -s 521 > /etc/mcias/server.key cert selfsign -p /etc/mcias/server.key -f /tmp/request.yaml > /etc/mcias/server.crt chmod 0640 /etc/mcias/server.key chown root:mcias /etc/mcias/server.key rm /tmp/request.yaml ``` **Option B: Using openssl** ```sh 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. Configure the server ```sh cp dist/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 ``` Minimum required fields: ```toml [server] listen_addr = "0.0.0.0:8443" tls_cert = "/etc/mcias/server.crt" tls_key = "/etc/mcias/server.key" [database] path = "/var/lib/mcias/mcias.db" [tokens] issuer = "https://auth.example.com" [master_key] passphrase_env = "MCIAS_MASTER_PASSPHRASE" ``` See `dist/mcias.conf.example` for the fully-commented reference configuration. For local development, use `dist/mcias-dev.conf.example`. ### 3. Set the master key passphrase ```sh cp dist/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. Create the first admin account ```sh export MCIAS_MASTER_PASSPHRASE=your-passphrase mciasdb --config /etc/mcias/mcias.conf account create \ --username admin --type human mciasdb --config /etc/mcias/mcias.conf account set-password --id mciasdb --config /etc/mcias/mcias.conf role grant --id --role admin ``` ### 5. Start the server ```sh # systemd systemctl enable --now mcias # manual MCIAS_MASTER_PASSPHRASE=your-passphrase mciassrv -config /etc/mcias/mcias.conf ``` ### 6. Verify ```sh curl -k https://localhost:8443/v1/health # {"status":"ok"} ``` --- ## Building ```sh make build # compile all binaries to bin/ make test # go test -race ./... make lint # golangci-lint run ./... make generate # regenerate protobuf stubs (requires protoc) make man # build compressed man pages make clean # remove bin/ and generated artifacts make dist # cross-compiled tarballs for linux/amd64 and linux/arm64 make docker # build Docker image mcias: ``` --- ## Admin CLI (mciasctl) ```sh TOKEN=$(curl -sk https://localhost:8443/v1/auth/login \ -d '{"username":"admin","password":"..."}' | jq -r .token) export MCIAS_TOKEN=$TOKEN mciasctl -server https://localhost:8443 account list mciasctl account create -username alice -password s3cr3t mciasctl role set -id $UUID -roles admin mciasctl token issue -id $SYSTEM_UUID mciasctl pgcreds set -id $UUID -host db.example.com -port 5432 \ -db mydb -user myuser -password mypassword ``` See `man mciasctl` for the full reference. --- ## Database Maintenance Tool (mciasdb) ```sh export MCIAS_MASTER_PASSPHRASE=your-passphrase CONF="--config /etc/mcias/mcias.conf" mciasdb $CONF schema verify mciasdb $CONF account list mciasdb $CONF account set-password --id $UUID mciasdb $CONF role grant --id $UUID --role admin mciasdb $CONF prune tokens mciasdb $CONF audit tail --n 50 mciasdb $CONF audit query --account $UUID --json ``` See `man mciasdb` for the full reference, including the trust model and safety warnings. --- ## gRPC Interface Enable the gRPC listener in config: ```toml [server] listen_addr = "0.0.0.0:8443" grpc_addr = "0.0.0.0:9443" tls_cert = "/etc/mcias/server.crt" tls_key = "/etc/mcias/server.key" ``` Using mciasgrpcctl: ```sh export MCIAS_TOKEN=$ADMIN_JWT mciasgrpcctl -server auth.example.com:9443 -cacert /etc/mcias/server.crt health mciasgrpcctl account list ``` Using grpcurl: ```sh grpcurl -cacert /etc/mcias/server.crt \ -H "authorization: Bearer $ADMIN_JWT" \ auth.example.com:9443 \ mcias.v1.AdminService/Health ``` See `man mciasgrpcctl` and [ARCHITECTURE.md](ARCHITECTURE.md) §17. --- ## Deploying with Docker ```sh make docker mkdir -p /srv/mcias/config cp dist/mcias.conf.docker.example /srv/mcias/config/mcias.conf $EDITOR /srv/mcias/config/mcias.conf docker run -d \ --name mcias \ -v /srv/mcias/config:/etc/mcias:ro \ -v mcias-data:/data \ -e MCIAS_MASTER_PASSPHRASE=your-passphrase \ -p 8443:8443 \ -p 9443:9443 \ mcias:latest curl -k https://localhost:8443/v1/health ``` The container runs as uid 10001 (mcias) with no capabilities. TLS termination happens inside the container. See `dist/mcias.conf.docker.example` for the config template. --- ## Man Pages ```sh man mciassrv # server reference man mciasctl # admin CLI (REST) man mciasdb # database maintenance tool man mciasgrpcctl # gRPC admin CLI ``` --- ## Security Notes - JWTs signed with Ed25519 (EdDSA); `alg` header validated before processing to defeat algorithm confusion attacks. - Passwords hashed with Argon2id at OWASP 2023 minimum parameters. - All secret material encrypted at rest with AES-256-GCM using the master key. - Credential fields never appear in any API response. - TLS 1.2 minimum protocol version. See [ARCHITECTURE.md](ARCHITECTURE.md) §2–3 for the full security model.