{
  "markdown": "<div align=\"center\">\n\n# vps-boot\n\n**From a fresh VPS to a ready-to-work dev environment.**\n\nSSH hardening, development runtimes and AI agents — one script, your choice of tools.\n\n`Ubuntu 26.04` · `amd64` · `Bash` · `MIT`\n\n[Get started](#get-started) · [Tools](#tools) · [Commands](#commands) · [Recovery](#recovery)\n\n</div>\n\n---\n\n## Get started\n\nStart with a **fresh Ubuntu 26.04 amd64 VPS**, with systemd, OpenSSH and root access. Run inside `tmux` or `screen` to keep the session alive during installation.\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/julienlegoux/vps-boot/main/vps-boot.sh | sudo bash -s install\n```\n\nThe wizard guides you through four choices:\n\n```text\n◇  User account    skip — run as root / create a sudo user\n◇  SSH port        random, editable\n◇  Install mode    Full install / Custom\n◇  Continue?       review and confirm\n```\n\n**Root-only is the default.** Create a user if you prefer a separate sudo account. SSH port 22 is rejected; ports 80 and 443 are reserved when Caddy is selected.\n\n> **Trying the next release?** Replace `main` with `develop` in the command above. See the [release verification record](docs/planning/release-0.1.0.md) for tested behavior and remaining acceptance checks.\n\n## What it takes care of\n\n| Your server | Your workspace | Your next session |\n|---|---|---|\n| System updates and build tools | Choose the tools you need | Resume interrupted installations |\n| UFW firewall and fail2ban | Dependencies installed automatically | Verify installed components |\n| SSH key enrollment and lockdown | Stable Python, Node LTS and more | Finish SSH hardening later |\n| Automatic security updates, no automatic reboot | Agent and cloud CLIs ready for sign-in | Keep the same account, port and selection |\n\nAPT waits up to **three minutes** for package locks. If a step fails, installation stops, prints the log tail and records progress for `resume`.\n\n## Tools\n\n**Full install** selects the whole catalogue: **22 components as root**, or **23 with a created user**. **Custom** lets you pick individual tools; prerequisites are added automatically.\n\n| Group | Includes |\n|---|---|\n| Core | CLI utilities, Docker + Compose, GitHub CLI, optional passwordless sudo |\n| Languages | Node, Python, Go, Java, Rust |\n| Packaging | Bun, pnpm, uv |\n| AI agents | Claude Code, opencode, Codex, Gemini CLI, pi, Hermes |\n| Cloud | Vercel, Neon, Hostinger |\n| Infrastructure | Caddy, herdr |\n\n<details>\n<summary><strong>Explore the full catalogue</strong></summary>\n\n### Toolchain — 23 components\n\n| Group | Tool | Purpose |\n|---|---|---|\n| core | Passwordless sudo | Passwordless sudo for a created user |\n| core | CLI tools | `jq`, `ripgrep`, `fd`, `htop`, `tree` |\n| core | Docker + Compose | Docker CE, buildx and Compose |\n| core | GitHub CLI | GitHub from the terminal |\n| languages | Node LTS | Current Node LTS via NodeSource |\n| languages | Python + pip | Stable Python via uv, with a dedicated pip environment |\n| languages | Go | Latest Go toolchain |\n| languages | Java (JDK) | Newest installable stable LTS OpenJDK |\n| languages | Rust | Shared rustup toolchain, per-user Cargo caches |\n| packaging | Bun | JavaScript runtime |\n| packaging | pnpm | JavaScript package manager |\n| packaging | uv | Python packages and virtual environments |\n| agents | Claude Code | Anthropic coding agent |\n| agents | opencode | Open-source coding agent |\n| agents | Codex | OpenAI coding agent |\n| agents | Gemini CLI | Google coding agent |\n| agents | pi | Terminal coding agent |\n| agents | Hermes | NousResearch AI agent |\n| cloud | Vercel CLI | `vercel` |\n| cloud | Neon CLI | `neonctl` |\n| cloud | Hostinger CLI | `hostinger` |\n| infra | Caddy | Web server and reverse proxy |\n| infra | herdr | Agent-aware terminal multiplexer |\n\nFull install includes Passwordless sudo only when you create a user. In Custom, Passwordless sudo appears as a checkbox for that user.\n\nNavigate with **arrow keys** or **hjkl**, toggle with **space**, select all with **a**, clear with **n**, and confirm with **Enter**. For the baseline alone, choose Custom and clear the selection.\n\n</details>\n\n## Commands\n\nWith a local copy of the script:\n\n| Command | Use it to… |\n|---|---|\n| `sudo ./vps-boot.sh install` | Start the wizard on a fresh server |\n| `sudo ./vps-boot.sh resume` | Continue interrupted or failed work |\n| `sudo ./vps-boot.sh check` | Verify the recorded installation |\n| `sudo ./vps-boot.sh harden` | Enroll a key and finish SSH lockdown |\n| `sudo ./vps-boot.sh --help` | Show options |\n\n**No local copy?** Use the same download command with the action you need:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/julienlegoux/vps-boot/main/vps-boot.sh | sudo bash -s resume\n```\n\n`resume` checks completed steps before skipping them and retries failed work. It requires a journal created by this version; legacy installations can still use `check` and `harden`.\n\n<details>\n<summary><strong>Account and port overrides</strong></summary>\n\n```bash\nsudo ./vps-boot.sh install julien 2222    # pre-fill the created account and port\nsudo ./vps-boot.sh harden julien         # enroll keys for this account\nsudo ./vps-boot.sh check root <port>     # verify a root-only setup\nsudo ./vps-boot.sh check <username> <port>\n```\n\nWithout overrides, `check` and `harden` read the account and port from `/etc/vps-boot/config`. `harden` takes no port argument: it uses the existing configuration.\n\n</details>\n\n## Finish with your SSH key\n\nThe wizard prints key-copy commands for **Linux, macOS and Windows**. Copy your key, then test it in a new terminal before confirming.\n\nThe installer applies final SSH lockdown only when you choose `ok` and a valid key exists. Choosing `skip`, or continuing with a missing or invalid key, leaves password authentication enabled. You can finish later:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/julienlegoux/vps-boot/main/vps-boot.sh | sudo bash -s harden\n```\n\n<details>\n<summary><strong>What lockdown changes</strong></summary>\n\nLockdown proceeds only after `authorized_keys` contains a valid SSH key. Only then does the script set `PasswordAuthentication no` and `KbdInteractiveAuthentication no`, validate the SSH configuration and reload `ssh.service`. Root-only installations use key-only root access; installations with a created user disable root login.\n\nUntil lockdown is complete, `check` reports a warning and the command to finish it.\n\n</details>\n\n## Network access\n\nUFW denies incoming traffic except on your selected SSH port. **Selecting Caddy also opens 80/443 TCP**; its default page may be available before you configure an application. UDP 443 is not opened automatically.\n\nDocker-published ports can bypass UFW. Bind private services to loopback or configure Docker's forwarding policy. See [Docker's firewall limitations](https://docs.docker.com/engine/install/ubuntu/#firewall-limitations).\n\n## Recovery\n\n**Installation stopped?** Inspect the log, resolve the reported error, then run `resume` with this version of the script.\n\n```bash\ntail -n 60 /var/log/vps-boot.log\n```\n\n**Lost SSH access?** Use your provider's web console. Restore the SSH configuration backup and correct or remove `/etc/ssh/sshd_config.d/00-vps-boot.conf`. Run `sshd -t` before reloading `ssh.service`, then verify with `check`.\n\n`install` refuses an existing installation. These commands do not upgrade Ubuntu or adopt an unmanaged server.\n\n<details>\n<summary><strong>State and runtime locations</strong></summary>\n\n- `/etc/vps-boot/` stores the account, port, component selection and progress journal. Passwords are never recorded; an interrupted user-creation step requests the password again.\n- `/opt/vps-boot/python` holds the uv-managed interpreter. `python` uses a dedicated development environment with pip; Ubuntu's `python3` stays unchanged. Use a virtual environment for each project.\n- Rust's toolchain is shared; Cargo caches live in each user's `~/.cargo`.\n\n</details>\n\n## Development\n\nWoodpecker runs Bash syntax checks, ShellCheck error checks and the regression suite on Ubuntu 26.04.\n\n```bash\ndocker build -t vps-boot-test:26.04 -f tests/Dockerfile .\ndocker run --rm -v \"$PWD:/workspace:ro\" vps-boot-test:26.04\nwoodpecker-cli lint .woodpecker/test.yaml\n```\n\n[Adding a component](.claude/CLAUDE.md) · [Technical specs](docs/planning/SPECS.md) · [Release verification](docs/planning/release-0.1.0.md)\n\n<details>\n<summary><strong>Service acceptance tests</strong></summary>\n\n`tests/smoke_user.sh` checks installed runtimes and CLIs as an unprivileged account. `tests/smoke_system.sh root` (or `user`) covers SSH, UFW, nested Docker, Caddy and resume after an injected failure.\n\nRun the system scenarios only in a **disposable privileged systemd container**, without the host Docker socket. They are separate from ordinary PR jobs. Docker tests do not establish VPS boot, cloud-init or provider-firewall compatibility.\n\n</details>\n\n---\n\nLicensed under **MIT**.\n",
  "bytes": 8940,
  "sha": "55b3e128c117930764ddc9681f6a28ee3ac9aece24d6e0cc99e705c23c5e0f35",
  "repo_slug": "julienlegoux/vps-boot",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_julienlegoux_vps_boot_docs_epics_index_m_e9cf1343/readme"
}