4.0 KiB
Hosting your web apps on mars
You can run web apps as containers and publish them on the home network at
http://mars.sol/<name>/, without anyone changing mars's configuration.
Everything below takes effect immediately — no restart, no redeploy.
This file is mounted read-only and is rewritten on every restart. Save what you need from it to your memory.
How it fits together
podmanin your shell does not run containers next to you. It talks, through$CONTAINER_HOST, to a separate unprivileged account on mars (luna-apps). Containers there keep running when you restart, and come back after mars reboots if they were started with--restart=always.- Caddy on mars routes
http://mars.sol/<name>/to the port you name in/opt/data/sites/<name>.json. A service on mars checks that file and writes the outcome to/opt/data/sites-status.txt.
Publish an app
-
Put the source under
/opt/data/apps/<name>/with aContainerfile(orDockerfile), and build it. The directory is uploaded, so this works from where you are:podman build -t localhost/<name> /opt/data/apps/<name> -
Run it. Publish its port on
127.0.0.1only, using a host port between @portMin@ and @portMax@ that no other app uses (podman psshows the taken ones):podman run -d --name <name> --restart=always \ -p 127.0.0.1:20001:8080 localhost/<name> -
Register it:
echo '{"port": 20001}' > /opt/data/sites/<name>.json -
Check that it took, then fetch it:
cat /opt/data/sites-status.txt curl -si http://127.0.0.1/<name>/It is now at
http://mars.sol/<name>/for anyone on the home network.
Rules the registry enforces
<name>is lowercase letters, digits and-, starts with a letter or digit, at most 32 characters. The file is/opt/data/sites/<name>.json.- The file holds exactly one JSON object, and only
portis read. portis an integer from @portMin@ to @portMax@. Anything else is rejected (that includes everything else already running on mars).- A rejected entry never affects the others.
sites-status.txtsays why. - If
sites-status.txtstarts withERROR, that is a fault on mars's side, not in your entry — tell darman.
Writing apps that work under //
Caddy strips /<name> before the request reaches your app, so the app itself
sees /, /style.css, /api/items. The browser, however, is at
http://mars.sol/<name>/, so every link, asset URL and fetch() in the page must
keep that prefix:
- Prefer relative URLs:
style.css,./api/items— not/style.css. - Or set the framework's public base URL to
/<name>/(e.g. Vite'sbase). Avoid settings that ALSO expect the prefix on incoming requests (Next.jsbasePath); the prefix has already been removed by then. - The original prefix arrives in the
X-Forwarded-Prefixheader. http://mars.sol/<name>redirects tohttp://mars.sol/<name>/.
Files and data
-v /opt/data/...:/somewheredoes not work: those paths exist only inside your container, andluna-appscannot see your files. Copy code into the image in theContainerfile.- Keep an app's state in a named volume:
-v <name>-data:/data. - Pulling public images works (
podman pull docker.io/library/nginx). - Do not copy tokens or anything else from
/opt/datainto an app. The apps cannot read your files; keep it that way.
Update, inspect, remove
- Update: rebuild,
podman rm -f <name>, run it again on the same port. The JSON file stays as it is. - Inspect:
podman ps -a,podman logs <name>,cat /opt/data/sites-status.txt. - Remove:
rm /opt/data/sites/<name>.json, thenpodman rm -f <name>, and optionallypodman rmi localhost/<name>andpodman volume rm <name>-data.
Limits
- Home network only: plain
http://, not reachable from the internet, not on mgaction.town. - There is no login in front of these apps. Anyone on the home network can use them, so do not publish anything that would be a problem to expose there.