<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ship.git/internal, branch agent-mode</title>
<subtitle>Deploy to your VPS in one command</subtitle>
<id>https://code.northwest.io/ship.git/atom?h=agent-mode</id>
<link rel='self' href='https://code.northwest.io/ship.git/atom?h=agent-mode'/>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/'/>
<updated>2026-02-17T15:59:50+00:00</updated>
<entry>
<title>Fix port collision bug, add --container-port flag</title>
<updated>2026-02-17T15:59:50+00:00</updated>
<author>
<name>Clawd</name>
<email>ai@clawd.bot</email>
</author>
<published>2026-02-17T15:59:50+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=d97bb6f53eefd2139115d39bca7e17d565222472'/>
<id>urn:sha1:d97bb6f53eefd2139115d39bca7e17d565222472</id>
<content type='text'>
Port allocation:
- Use atomic flock-based allocation via /etc/ship/next_port
- Prevents race conditions when multiple deploys run concurrently
- Each app still gets its port stored in /etc/ship/ports/&lt;name&gt;

Docker container port:
- Add --container-port flag (default 80)
- Template now uses {{.ContainerPort}} instead of hardcoded 80
- Supports containers that listen on 8080, 3000, etc.
</content>
</entry>
<entry>
<title>Remove v1 code, simplify state to just base_domain</title>
<updated>2026-02-17T15:54:26+00:00</updated>
<author>
<name>Clawd</name>
<email>ai@clawd.bot</email>
</author>
<published>2026-02-17T15:54:26+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=6b2c04728cd914f27ae62c1df0bf5df24ac9a628'/>
<id>urn:sha1:6b2c04728cd914f27ae62c1df0bf5df24ac9a628</id>
<content type='text'>
- Delete all v1 commands (deploy, init, list, status, remove, etc.)
- Delete v1 env/ and host/ subcommand directories
- Simplify state.go: remove NextPort, Apps, AllocatePort, etc.
- Local state now only tracks default_host + base_domain per host
- Ports and deploys are tracked on the server (/etc/ship/ports/)
- host init now creates minimal state.json
</content>
</entry>
<entry>
<title>Fix Docker port mapping: map host port to container port 80</title>
<updated>2026-02-17T01:18:07+00:00</updated>
<author>
<name>Clawd</name>
<email>ai@clawd.bot</email>
</author>
<published>2026-02-17T01:18:07+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=3cd1ee83993b2543a7701a48d048c417c52bfdcb'/>
<id>urn:sha1:3cd1ee83993b2543a7701a48d048c417c52bfdcb</id>
<content type='text'>
Most Docker web containers (nginx, etc.) listen on port 80 internally.
The previous mapping assumed the container listened on the allocated port.
</content>
</entry>
<entry>
<title>fix: make ErrorResponse implement error interface for v1 compat</title>
<updated>2026-02-16T02:57:28+00:00</updated>
<author>
<name>Clawd</name>
<email>ai@clawd.bot</email>
</author>
<published>2026-02-16T02:57:28+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=626055c95ded6ef22c913b47266125884a84fa1c'/>
<id>urn:sha1:626055c95ded6ef22c913b47266125884a84fa1c</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat(v2): implement ship host init with JSON output</title>
<updated>2026-02-16T02:52:55+00:00</updated>
<author>
<name>Clawd</name>
<email>ai@clawd.bot</email>
</author>
<published>2026-02-16T02:52:55+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=a7436dfcc01a599bbb99a810bd59e92b21252c78'/>
<id>urn:sha1:a7436dfcc01a599bbb99a810bd59e92b21252c78</id>
<content type='text'>
- host_v2.go: full host initialization with JSON responses
- Installs Caddy, Docker on Ubuntu/Debian
- Creates /etc/ship/{env,ports,ttl} directories
- Installs TTL cleanup timer (hourly systemd timer)
- Cleanup script removes expired deploys completely
- Preserves git deploy setup functionality (optional)
- Added ErrInvalidArgs error code

Critical 'host init' functionality preserved for v2
</content>
</entry>
<entry>
<title>feat(v2): add output and detect packages</title>
<updated>2026-02-16T02:47:15+00:00</updated>
<author>
<name>Clawd</name>
<email>ai@clawd.bot</email>
</author>
<published>2026-02-16T02:47:15+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=5b8893550130ad8ffe39a6523a11994757493691'/>
<id>urn:sha1:5b8893550130ad8ffe39a6523a11994757493691</id>
<content type='text'>
- internal/output: JSON response types, error codes, exit codes, pretty output
- internal/detect: auto-detection of project type (static/docker/binary)
- PROGRESS.md: track rebuild progress

Foundation for agent-first JSON interface per SPEC.md
</content>
</entry>
<entry>
<title>Add cgit web interface for browsing repos</title>
<updated>2026-02-14T15:56:22+00:00</updated>
<author>
<name>bndw</name>
<email>ben@bdw.to</email>
</author>
<published>2026-02-14T15:56:22+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=f0dfabe5b7f1f8d23169c6e62a2f0c27bd6c5463'/>
<id>urn:sha1:f0dfabe5b7f1f8d23169c6e62a2f0c27bd6c5463</id>
<content type='text'>
Adds cgit as a web frontend for browsing git repositories. Visiting the
base domain now shows a cgit repo index with trees, commits, diffs, and
blame views. Public repos (marked with git-daemon-export-ok) are browsable
and cloneable over HTTPS.

- Install cgit during host init
- Configure cgit with dark theme and base domain integration
- Add cgit CGI handler to base domain Caddyfile
- Update README to emphasize git-centric workflow with cgit frontend
</content>
</entry>
<entry>
<title>Remove --module flag, add --public, make hooks smarter</title>
<updated>2026-02-11T05:29:20+00:00</updated>
<author>
<name>bndw</name>
<email>ben@bdw.to</email>
</author>
<published>2026-02-11T05:29:20+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=c49a067ac84ac5c1691ecf4db6a9bf791246899f'/>
<id>urn:sha1:c49a067ac84ac5c1691ecf4db6a9bf791246899f</id>
<content type='text'>
Drop git-module type — the post-receive hook now checks for a Dockerfile
before building, so repos without one simply skip deploy on push. This
covers Go modules and libraries that only need vanity imports.

Add --public flag to ship init for per-repo HTTPS clone visibility.
Show visibility column in ship list.
</content>
</entry>
<entry>
<title>Harden security: name validation, scoped sudoers, safe.directory</title>
<updated>2026-02-11T05:29:08+00:00</updated>
<author>
<name>bndw</name>
<email>ben@bdw.to</email>
</author>
<published>2026-02-11T05:29:08+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=47d4b3b6e4d68660e6e1e05fe2e1c0839f86e40e'/>
<id>urn:sha1:47d4b3b6e4d68660e6e1e05fe2e1c0839f86e40e</id>
<content type='text'>
- Add ValidateName() enforcing ^[a-z][a-z0-9-]{0,62}$ on all entry points
- Tighten sudoers to restrict cp sources/destinations and chown targets
- Scope git safe.directory to www-data user only (preserves CVE-2022-24765)
- Add www-data to git group and caddy to www-data group for fcgiwrap
- Fix vanity import template to use orig_uri placeholder
- Restart (not reload) services after group changes
- Add name validation to env subcommands and deploy_cmd
</content>
</entry>
<entry>
<title>Add git-centric deployment with Docker builds and vanity imports</title>
<updated>2026-02-08T20:32:59+00:00</updated>
<author>
<name>bndw</name>
<email>ben@bdw.to</email>
</author>
<published>2026-02-08T20:32:59+00:00</published>
<link rel='alternate' type='text/html' href='https://code.northwest.io/ship.git/commit/?id=a8ad8e934d15d2bf84f942414a89af1d2691adbc'/>
<id>urn:sha1:a8ad8e934d15d2bf84f942414a89af1d2691adbc</id>
<content type='text'>
New deployment model where projects start with a git remote on the VPS.
Pushing to the remote triggers automatic docker build and deploy via
post-receive hooks. The base domain serves Go vanity imports and git
HTTPS cloning via Caddy + fcgiwrap.

- Add `ship init &lt;name&gt;` command to create bare repos and .ship/ config
- Add `ship deploy &lt;name&gt;` command for manual rebuilds
- Extend `ship host init --base-domain` to set up Docker, git user,
  fcgiwrap, sudoers, and vanity import infrastructure
- Add git-app and git-static types alongside existing app and static
- Update remove, status, logs, restart, list, and config-update to
  handle new types
</content>
</entry>
</feed>
