added code-server
This commit is contained in:
@@ -38,6 +38,7 @@ handled separately — see [Exposing services](#exposing-services).
|
|||||||
|---------|------|-------|
|
|---------|------|-------|
|
||||||
| [audiobookshelf](audiobookshelf/) | 13378 | Audiobooks and podcasts, with per-user progress sync |
|
| [audiobookshelf](audiobookshelf/) | 13378 | Audiobooks and podcasts, with per-user progress sync |
|
||||||
| [cloudflare-tunnel](cloudflare-tunnel/) | — | Outbound connector. Exposes other services without opening a port |
|
| [cloudflare-tunnel](cloudflare-tunnel/) | — | Outbound connector. Exposes other services without opening a port |
|
||||||
|
| [codeserver](codeserver/) | 8443 | VS Code in a browser. Effectively a remote shell — read its README before exposing |
|
||||||
| [jellyfin](jellyfin/) | 8096 | Media streaming. Also 7359/udp for auto-discovery |
|
| [jellyfin](jellyfin/) | 8096 | Media streaming. Also 7359/udp for auto-discovery |
|
||||||
| [openwebui](openwebui/) | 3033 | LLM chat UI. One `OWUI_TAG` switches between CPU, CUDA and bundled-Ollama |
|
| [openwebui](openwebui/) | 3033 | LLM chat UI. One `OWUI_TAG` switches between CPU, CUDA and bundled-Ollama |
|
||||||
| [overleaf](overleaf/) | 8020 | LaTeX editor. Four containers: app, Mongo (replica set), Redis, init |
|
| [overleaf](overleaf/) | 8020 | LaTeX editor. Four containers: app, Mongo (replica set), Redis, init |
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Copy to .env and adjust. .env is git-ignored; this file is not.
|
||||||
|
|
||||||
|
# ─── Required ───────────────────────────────────────────────────────
|
||||||
|
# Web UI password. There is no default and no "first run" setup: if neither
|
||||||
|
# PASSWORD nor HASHED_PASSWORD is set, code-server serves an editor and a
|
||||||
|
# terminal with NO authentication whatsoever.
|
||||||
|
PASSWORD=
|
||||||
|
|
||||||
|
# Instead of the plaintext above, you can store only a hash. It overrides
|
||||||
|
# PASSWORD when set. Generate one with:
|
||||||
|
#
|
||||||
|
# echo -n "yourpassword" | npx argon2-cli -e
|
||||||
|
#
|
||||||
|
# Then uncomment HASHED_PASSWORD in compose.yaml.
|
||||||
|
#HASHED_PASSWORD=
|
||||||
|
|
||||||
|
# ─── Sudo inside the container ──────────────────────────────────────
|
||||||
|
# Set this if you want to install things from the built-in terminal. The image
|
||||||
|
# is deliberately minimal -- no python, no pip, no compilers -- so anything
|
||||||
|
# beyond editing needs apt:
|
||||||
|
#
|
||||||
|
# sudo apt update && sudo apt install -y python3-pip
|
||||||
|
#
|
||||||
|
# Leaving it empty is safe and simply disables sudo; the init script tests for
|
||||||
|
# a non-empty value, so empty is not an enabled blank password. It can be the
|
||||||
|
# same as PASSWORD or different -- it only guards `sudo` inside the container.
|
||||||
|
#
|
||||||
|
# Be aware of what it grants: root in the container. That is a container, not
|
||||||
|
# your host, but it is still root over anything you have mounted.
|
||||||
|
SUDO_PASSWORD=
|
||||||
|
|
||||||
|
# Store a hash instead of the plaintext. Takes priority over SUDO_PASSWORD.
|
||||||
|
# Format is $type$salt$hash. Uncomment the matching line in compose.yaml.
|
||||||
|
#SUDO_PASSWORD_HASH=
|
||||||
|
|
||||||
|
# ─── Identity ───────────────────────────────────────────────────────
|
||||||
|
# Files you create in the editor are owned by this user. `id -u` / `id -g`.
|
||||||
|
# Defaulted to 1000/1000 in compose.yaml.
|
||||||
|
#PUID=1000
|
||||||
|
#PGID=1000
|
||||||
|
#TZ=Europe/Paris
|
||||||
|
|
||||||
|
# ─── Paths ──────────────────────────────────────────────────────────
|
||||||
|
# Settings, installed extensions, and the default workspace.
|
||||||
|
#CONFIG_PATH=./config
|
||||||
|
|
||||||
|
# Optional: existing code on the host to expose in the editor. Uncomment the
|
||||||
|
# matching volume line in compose.yaml too.
|
||||||
|
#PROJECTS_PATH=/srv/projects
|
||||||
|
|
||||||
|
# ─── Ports and proxying ─────────────────────────────────────────────
|
||||||
|
#PORT=8443
|
||||||
|
#DEFAULT_WORKSPACE=/config/workspace
|
||||||
|
|
||||||
|
# Only for subdomain port-forwarding (3000.code.example.com). Needs wildcard
|
||||||
|
# DNS and a wildcard certificate; skip it if you don't need that.
|
||||||
|
#PROXY_DOMAIN=code.example.com
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
# code-server
|
||||||
|
|
||||||
|
VS Code in a browser. Useful for editing on the NAS from a laptop, a tablet, or
|
||||||
|
any machine you don't want to set a toolchain up on.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
$EDITOR .env # PASSWORD is required
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://<host>:8443`. The password from `.env` is the only credential.
|
||||||
|
|
||||||
|
## Ports
|
||||||
|
|
||||||
|
| Port | Proto | Purpose |
|
||||||
|
|------|-------|---------|
|
||||||
|
| 8443 | http | Editor UI (plain HTTP — put TLS in front of it) |
|
||||||
|
|
||||||
|
## Read this before exposing it
|
||||||
|
|
||||||
|
code-server is not a document editor with a terminal bolted on. It **is** a
|
||||||
|
shell, with a file browser, running as `PUID`/`PGID`, with network access to
|
||||||
|
everything the container can reach. Treat exposing it exactly as you'd treat
|
||||||
|
exposing SSH.
|
||||||
|
|
||||||
|
Three consequences worth being deliberate about:
|
||||||
|
|
||||||
|
**`PASSWORD` is required here** (`${PASSWORD:?…}`), which is a deviation from
|
||||||
|
upstream's example. Their compose marks it `#optional`, and it is — but the
|
||||||
|
docs also say: *"If PASSWORD or HASHED_PASSWORD is not provided, there will be
|
||||||
|
no auth."* Optional-and-silently-open is the wrong default for something that
|
||||||
|
hands out a shell, so this stack refuses to start without one.
|
||||||
|
|
||||||
|
**`SUDO_PASSWORD` is how you install anything.** The image is deliberately
|
||||||
|
minimal — no python, no pip, no compilers — so `sudo apt install python3-pip`
|
||||||
|
is the normal first move, and that needs sudo enabled. It grants root *in the
|
||||||
|
container*, which is a real boundary but not your host. Leave it empty if you
|
||||||
|
only ever edit; the init script tests for a non-empty value, so empty means
|
||||||
|
disabled rather than an enabled blank password.
|
||||||
|
|
||||||
|
**Whatever you mount is executable, not just editable.** The commented
|
||||||
|
`PROJECTS_PATH` line is genuinely convenient and genuinely a decision — mount
|
||||||
|
your code, not your whole home directory. Never mount `/var/run/docker.sock`
|
||||||
|
here; that converts a container password into root on the host.
|
||||||
|
|
||||||
|
## Why it looks like this
|
||||||
|
|
||||||
|
**LinuxServer image**, so the usual `PUID`/`PGID`/`TZ` contract applies and
|
||||||
|
files you create are owned by you rather than root. Same reasoning as
|
||||||
|
[jellyfin](../jellyfin/) — one dialect across the stacks.
|
||||||
|
|
||||||
|
**`HASHED_PASSWORD` is offered but commented.** `.env` is git-ignored, so a
|
||||||
|
plaintext password there is not exposed, but the hash means the credential
|
||||||
|
isn't sitting in a readable file at all. Generate one with
|
||||||
|
`echo -n "yourpassword" | npx argon2-cli -e`. It overrides `PASSWORD` when set.
|
||||||
|
|
||||||
|
**`PROXY_DOMAIN` is commented out.** It only matters if you want forwarded
|
||||||
|
ports served as subdomains — port 3000 as `3000.code.example.com` — which needs
|
||||||
|
a wildcard DNS record and a wildcard certificate. Without it, forwarded ports
|
||||||
|
still work through the editor's own proxy path.
|
||||||
|
|
||||||
|
**`DEFAULT_WORKSPACE` is set** so the editor opens somewhere useful instead of
|
||||||
|
an empty file picker on every visit.
|
||||||
|
|
||||||
|
## What survives a rebuild, and what doesn't
|
||||||
|
|
||||||
|
`/config` is the app user's home directory — `abc:x:911:1001::/config` — and
|
||||||
|
it's the only persisted path. That single fact decides how you should install
|
||||||
|
things:
|
||||||
|
|
||||||
|
| Installed with | Lands in | Survives `docker compose up` after a pull? |
|
||||||
|
|---|---|---|
|
||||||
|
| `sudo apt install …` | `/usr/…` | **No** — gone with the old container |
|
||||||
|
| `pip install --user …` | `/config/.local` | Yes |
|
||||||
|
| VS Code extensions | `/config` | Yes |
|
||||||
|
| Anything in your workspace | `/config/workspace` | Yes |
|
||||||
|
|
||||||
|
So `sudo apt install python3-pip` has to be repeated after every image update,
|
||||||
|
while the packages you then `pip install --user` stay put. Prefer `--user`
|
||||||
|
installs, and keep a note of the apt packages you need so you can replay them.
|
||||||
|
|
||||||
|
If a toolchain matters enough that re-running apt annoys you, build a small
|
||||||
|
image `FROM lscr.io/linuxserver/code-server` with the packages baked in.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- **Extensions live in `/config`.** They're part of what to back up, and
|
||||||
|
they're why the config directory grows.
|
||||||
|
- **The VS Code Marketplace isn't available.** code-server uses Open VSX, so a
|
||||||
|
few Microsoft-licensed extensions are missing. Most have equivalents.
|
||||||
|
- **Port forwarding is per-session.** Ports you open inside the editor are
|
||||||
|
reachable through it, not published on the host.
|
||||||
|
- **A container password is a weaker boundary than it looks.** Anyone who logs
|
||||||
|
in can reach every service on your Docker network directly by name.
|
||||||
|
|
||||||
|
## Exposing it
|
||||||
|
|
||||||
|
- [Reverse proxy with Caddy](../docs/reverse-proxy.md) — the minimum. Never
|
||||||
|
serve this over plain HTTP off your LAN; the password crosses the wire.
|
||||||
|
- [Single sign-on with Authentik](../docs/authentik-sso.md) — a good fit here.
|
||||||
|
Forward auth in front of code-server means an attacker needs to get past
|
||||||
|
Authentik before reaching a login form that leads to a shell.
|
||||||
|
- [Cloudflare Tunnel](../cloudflare-tunnel/) — works, and avoids opening a port.
|
||||||
|
Pair it with Cloudflare Access rather than relying on the password alone.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Image docs: <https://docs.linuxserver.io/images/docker-code-server/>
|
||||||
|
- Upstream: <https://github.com/coder/code-server>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
services:
|
||||||
|
code-server:
|
||||||
|
image: lscr.io/linuxserver/code-server:latest
|
||||||
|
container_name: code-server
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- PUID=${PUID:-1000}
|
||||||
|
- PGID=${PGID:-1000}
|
||||||
|
- TZ=${TZ:-Etc/UTC}
|
||||||
|
|
||||||
|
# REQUIRED. With neither PASSWORD nor HASHED_PASSWORD set, code-server
|
||||||
|
# starts with NO authentication -- an editor and a shell, open to anyone
|
||||||
|
# who can reach the port.
|
||||||
|
- PASSWORD=${PASSWORD:?set one - without it code-server has no auth at all}
|
||||||
|
|
||||||
|
# Overrides PASSWORD when set. Use it to keep the plaintext out of .env.
|
||||||
|
#- HASHED_PASSWORD=${HASHED_PASSWORD}
|
||||||
|
|
||||||
|
# Enables `sudo` in the built-in terminal -- needed to apt-install
|
||||||
|
# anything, since the image ships no python/pip/compilers. Empty is safe
|
||||||
|
# and simply leaves sudo disabled: the init script tests `-n`, so an
|
||||||
|
# empty value is not the same as an enabled blank password.
|
||||||
|
- SUDO_PASSWORD=${SUDO_PASSWORD:-}
|
||||||
|
# Takes priority over SUDO_PASSWORD if you'd rather store only a hash.
|
||||||
|
#- SUDO_PASSWORD_HASH=${SUDO_PASSWORD_HASH}
|
||||||
|
|
||||||
|
# Only needed if you serve forwarded ports on subdomains, so that
|
||||||
|
# port 3000 becomes 3000.code.example.com. Requires a wildcard DNS
|
||||||
|
# record and a wildcard certificate.
|
||||||
|
#- PROXY_DOMAIN=${PROXY_DOMAIN}
|
||||||
|
|
||||||
|
- DEFAULT_WORKSPACE=${DEFAULT_WORKSPACE:-/config/workspace}
|
||||||
|
#- PWA_APPNAME=${PWA_APPNAME:-code-server}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# Settings, extensions, and the default workspace. Back this up.
|
||||||
|
- ${CONFIG_PATH:-./config}:/config
|
||||||
|
# Code that lives elsewhere on the host. Whatever you mount here is
|
||||||
|
# editable -- and runnable -- from the browser.
|
||||||
|
#- ${PROJECTS_PATH}:/config/workspace/projects
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "${PORT:-8443}:8443"
|
||||||
Reference in New Issue
Block a user