{"id":50248278,"url":"https://github.com/unclefi1/step-ca-ui","last_synced_at":"2026-05-27T00:01:31.890Z","repository":{"id":352903188,"uuid":"1213805749","full_name":"UncleFi1/step-ca-ui","owner":"UncleFi1","description":"Self-hosted web UI for Smallstep step-ca — manage your private PKI from a browser","archived":false,"fork":false,"pushed_at":"2026-05-25T19:58:53.000Z","size":252,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T21:32:09.088Z","etag":null,"topics":["certificate-authority","docker","docker-compose","golang","pki","self-hosted","smallstep","ssl","step-ca","tls","web-ui"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UncleFi1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-17T19:30:09.000Z","updated_at":"2026-05-25T19:58:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/UncleFi1/step-ca-ui","commit_stats":null,"previous_names":["unclefi1/step-ca-ui"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/UncleFi1/step-ca-ui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UncleFi1%2Fstep-ca-ui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UncleFi1%2Fstep-ca-ui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UncleFi1%2Fstep-ca-ui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UncleFi1%2Fstep-ca-ui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UncleFi1","download_url":"https://codeload.github.com/UncleFi1/step-ca-ui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UncleFi1%2Fstep-ca-ui/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33543973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"ssl_error","status_checked_at":"2026-05-26T15:22:15.568Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["certificate-authority","docker","docker-compose","golang","pki","self-hosted","smallstep","ssl","step-ca","tls","web-ui"],"created_at":"2026-05-27T00:01:30.174Z","updated_at":"2026-05-27T00:01:31.879Z","avatar_url":"https://github.com/UncleFi1.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Step-CA UI\n\n**Self-hosted web interface for [Smallstep step-ca](https://smallstep.com/docs/step-ca/) — manage your private PKI from a browser.**\n\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n[![Made with Go](https://img.shields.io/badge/Made%20with-Go%201.22-00ADD8.svg)](https://go.dev)\n[![Docker](https://img.shields.io/badge/Docker-Compose-2496ED.svg)](https://docs.docker.com/compose/)\n[![Latest release](https://img.shields.io/github/v/release/UncleFi1/step-ca-ui?label=release\u0026color=success)](https://github.com/UncleFi1/step-ca-ui/releases/latest)\n\n🇬🇧 **English** · [🇷🇺 Русский](README.ru.md)\n\n\u003c/div\u003e\n\n---\n\n\u003e A small-team-friendly web UI on top of `smallstep/step-ca`. No SaaS, no telemetry, no vendor lock-in — runs entirely on your own server in three Docker containers.\n\n## Features\n\n- 📋 **Certificate management** — issue, renew, revoke and import X.509 certificates\n- 👥 **Role-based access** — `admin` / `manager` / `viewer`\n- ⏱️ **Temporary users** — short-lived guest accounts with automatic expiration *(new in v1.4.0)*\n- 📅 **Custom date picker** — site-themed, no native browser widget *(new in v1.4.0)*\n- 🌍 **Timezone-aware** — configurable with the `TZ` environment variable\n- 🎨 **4 themes** — dark, light, blue, auto (follows OS)\n- 🧭 **Admin workspace** — polished admin UI with matching dark, light and blue themes *(new in v1.4.11)*\n- 🛡️ **Built-in security** — CSRF tokens, rate limiting, IP blocking, security log\n- 🌐 **Provisioner inspection** — list and edit step-ca provisioners\n- 💾 **Backup export** — admin UI and CLI backup bundles with manifest checksums *(new in v1.4.9)*\n\n## Quick Start\n\n```bash\ngit clone https://github.com/UncleFi1/step-ca-ui.git\ncd step-ca-ui\nsudo ./install.sh\n```\n\nThe installer can run in Russian or English and supports both clean installs and\nsafe updates:\n\n```bash\nsudo ./install.sh --mode install --lang en\nsudo ./install.sh --mode update --lang en\n```\n\nUpdate mode creates a backup first, preserves `.env` and Docker volumes, then\nruns `docker compose up -d --build`. It does not run `docker compose down -v`.\n\nThat's it. The installer:\n1. Detects your OS and installs Docker if needed\n2. Auto-detects your server IP (with confirmation)\n3. Generates strong passwords for everything\n4. Writes `.env` and `credentials.txt` (chmod 600)\n5. Builds and starts the containers\n6. Prints the URL and admin password\n\nThe whole thing takes 2–4 minutes on a fresh VM.\n\n## Requirements\n\n|                | Minimum | Recommended | High-load |\n|----------------|---------|-------------|-----------|\n| **CPU**        | 1 vCPU  | 2 vCPU      | 4+ vCPU   |\n| **RAM**        | 1 GB    | 2 GB        | 4+ GB     |\n| **Disk**       | 5 GB    | 20 GB SSD   | 50+ GB NVMe |\n| **Network**    | 10 Mbit/s | 100 Mbit/s | 1 Gbit/s  |\n| **Users**      | up to 50 | up to 500  | 500+      |\n| **Certificates**| up to 500 | up to 10k | 10k+     |\n\n**Software:**\n- Linux kernel 4.4+ (Ubuntu 20.04+, Debian 11+, CentOS Stream 9+, Rocky 9+, Alma 9+)\n- Docker Engine 20.10+ with Compose plugin v2+\n- Open ports: `443/tcp` (HTTPS UI), optionally `9000/tcp` (step-ca API)\n\n\u003e Untested but should work: macOS / Windows via Docker Desktop (development only). \\\n\u003e **Not supported:** shared hosting without Docker, Raspberry Pi Zero (insufficient RAM).\n\n## Stack\n\n| Layer        | Technology                  |\n|--------------|-----------------------------|\n| Backend      | Go 1.22, [chi](https://github.com/go-chi/chi) router |\n| Frontend     | Server-rendered HTML + vanilla JS, no build step |\n| Database     | PostgreSQL 16 |\n| CA           | [smallstep/step-ca](https://hub.docker.com/r/smallstep/step-ca) |\n| Deploy       | Docker Compose |\n| Container OS | Alpine 3.19 + tzdata        |\n\n## Architecture\n\n```\n                          ┌────────────┐\n   Browser  ─── HTTPS ───►│  step-ui   │  Go web app, port 8443\n                          │  (chi)     │\n                          └──┬─────┬───┘\n                             │     │\n                  SQL ◄──────┘     └──────► HTTPS API\n                             │     │\n                          ┌──▼──┐ ┌▼──────────┐\n                          │ pg  │ │ step-ca   │  port 9000\n                          │ 16  │ │ (PKI)     │\n                          └─────┘ └───────────┘\n\n   step-ui exposes :443  →  internally redirects to :8443\n   step-ca exposes :9000 →  internal-only by default\n```\n\n## Roles\n\n| Role    | View | Issue/Import | Revoke | Manage Users |\n|---------|------|--------------|--------|--------------|\n| viewer  | ✅   | ❌           | ❌     | ❌           |\n| manager | ✅   | ✅           | ❌     | ❌           |\n| admin   | ✅   | ✅           | ✅     | ✅           |\n\n**Temporary users** can have any role; they're auto-blocked when `expires_at` passes (a goroutine checks every minute).\n\n## Security\n\n- ✅ **CSRF protection** — tokens on every form and server-side checks on POST routes\n- ✅ **Rate limiting** — 5 failed login attempts → 15-minute IP block\n- ✅ **Security headers** — CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, optional HSTS\n- ✅ **Session timeout** — 8 hours, sliding\n- ✅ **Login audit log** — every login attempt is recorded with IP and User-Agent\n- ✅ **Self-signed TLS** — auto-generated on first boot, 10-year validity\n- ✅ **Password hashing** — bcrypt for new/updated passwords, with transparent migration from legacy SHA-256 hashes on next successful login\n\n\u003e 🔒 **Production tip:** put step-ui behind a reverse proxy (Caddy/nginx) with a real TLS certificate, restrict access via VPN/Tailscale, and back up the `step-ca-data` volume regularly.\n\n## Configuration\n\nAll configuration lives in `.env`. The installer creates this file for you, but you can edit it manually:\n\n```env\nHOST_IP=192.168.1.100              # SAN in self-signed cert; step-ca DNS\nUI_HTTPS_PORT=443                  # external HTTPS port\nPROVISIONER=admin                  # step-ca provisioner identifier\nCA_PASSWORD=\u003cgenerated\u003e            # step-ca provisioner password\nSECRET_KEY=\u003cgenerated\u003e             # session/CSRF signing key\nSESSION_SECURE=true                # secure session cookie over HTTPS\nENABLE_HSTS=false                  # enable only when using a trusted TLS certificate\nPOSTGRES_PASSWORD=\u003cgenerated\u003e      # database password\nTZ=UTC                             # container timezone\nSTEPCA_DEFAULT_TLS_CERT_DURATION=8760h\nSTEPCA_MAX_TLS_CERT_DURATION=87600h\n```\n\nAfter changing `.env`, recreate the containers:\n\n```bash\nsudo docker compose up -d --force-recreate\n```\n\n## FAQ\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eHow do I change the HTTPS port from 443?\u003c/b\u003e\u003c/summary\u003e\n\nEdit `docker-compose.yml`:\n```yaml\nservices:\n  step-ui:\n    ports:\n      - \"8443:8443\"   # was \"443:8443\"\n```\nThen restart: `sudo docker compose up -d --force-recreate step-ui`.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eHow do I back up and restore the data?\u003c/b\u003e\u003c/summary\u003e\n\nUse the admin UI: `Admin -\u003e Backup -\u003e Download backup bundle`.\n\nCLI export is also supported:\n\n```bash\nsudo ./install.sh --mode backup --lang en\n```\n\nBackups include PostgreSQL, `step-ca-data`, Step-CA UI data/certs/uploads and\n`manifest.json` with SHA-256 checksums. Restore is manual by design; follow\n[BACKUP_RESTORE.md](BACKUP_RESTORE.md).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eHow do I reset the admin password?\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nsudo docker compose exec postgres psql -U stepui -d stepui -c \\\n  \"UPDATE users SET password_hash = encode(sha256('newpass'::bytea), 'hex') WHERE username='admin';\"\n```\nThen log in with `admin` / `newpass` and change it from the UI.\nThe legacy SHA-256 reset value is accepted for recovery and is rehashed to bcrypt after login.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eThe browser warns about a self-signed certificate. How do I use my own?\u003c/b\u003e\u003c/summary\u003e\n\nReplace `step-ui-go/ssl/server.crt` and `server.key` with your own cert + key (e.g. from Let's Encrypt or your internal CA), then restart `step-ui`. Make sure the cert covers your `HOST_IP` or hostname.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eCan I run this behind Cloudflare / Caddy / nginx?\u003c/b\u003e\u003c/summary\u003e\n\nYes. Point your reverse proxy at `step-ui:8443` (HTTPS upstream) or change step-ui to plain HTTP and put TLS termination on the proxy. Set `X-Forwarded-Proto: https` so step-ui generates correct URLs.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eHow do I update to a new version?\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nsudo ./install.sh --mode update --lang en\n```\nThe update mode creates a backup first, keeps existing Docker volumes, optionally checks out a selected tag, and runs migrations automatically on startup. Always check the [release notes](https://github.com/UncleFi1/step-ca-ui/releases) first — major versions may have breaking changes.\n\u003c/details\u003e\n\n## Contributing\n\nPull requests are welcome. For major changes, please open an issue first to discuss what you'd like to change.\n\n```bash\ngit clone https://github.com/UncleFi1/step-ca-ui.git\ncd step-ca-ui/step-ui-go\ngo mod download\ngo run .  # requires running postgres + step-ca\n```\n\nWhen submitting:\n- Run `gofmt -w .` and `go vet ./...`\n- Update relevant tests\n- Keep commits focused and descriptive\n\n## Project structure\n\n```\n.\n├── docker-compose.yml         # 3 services: postgres, step-ca, step-ui\n├── .env.example               # configuration template\n├── install.sh                 # one-shot installer\n├── LICENSE                    # GPL-3.0\n├── README.md                  # this file (English)\n├── README.ru.md               # Russian translation\n└── step-ui-go/\n    ├── main.go                # entry point, router setup\n    ├── config/                # env-based config loader\n    ├── db/                    # all SQL queries\n    ├── handlers/              # HTTP handlers (one file per area)\n    ├── middleware/            # auth, security headers, CSRF\n    ├── models/                # data structs\n    ├── security/              # password hashing, rate limiting, CSRF\n    ├── templates/             # HTML templates (Go html/template)\n    ├── static/                # CSS, JS, favicon, images\n    ├── Dockerfile             # multi-stage Alpine build\n    └── entrypoint.sh          # waits for deps, generates SSL, starts app\n```\n\n## License\n\nThis project is licensed under the **GNU General Public License v3.0** — see the [LICENSE](LICENSE) file for details.\n\nIn short: you can use, modify, and distribute this software, but any derivative work must also be released under GPLv3.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funclefi1%2Fstep-ca-ui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funclefi1%2Fstep-ca-ui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funclefi1%2Fstep-ca-ui/lists"}