PI 'N' Stars is a Linux port of N.I.N.A. – Nighttime Imaging 'N' Astronomy, the astrophotography suite. It runs headless: there is no desktop window, you control it from the Touch-N-Stars web UI or app in your browser, on your phone or tablet.
This image contains the complete pins server in one container, the equivalent of a full pins installation on a Raspberry Pi:
indiserver, core drivers) plus the indi-3rdparty vendor drivers for ZWO, QHY, ToupTek, Player One, SVBony, Atik, FLI, SBIG and moreSource, Dockerfile and full documentation: https://github.com/aduffeck/pins (see docker/README.md).
mkdir -p data/home data/images
docker run -d --name pins --network host --stop-timeout 90 \
-v "$PWD/data/home:/home/pins" \
-v "$PWD/data/images:/home/pins/Documents/N.I.N.A" \
--privileged -v /dev/bus/usb:/dev/bus/usb \
aduffeck/pins:latest
Then open http://<host>:5000 for the Touch-N-Stars web UI. The container reports healthy in docker ps once the core server is up (allow up to 90 seconds on the first start).
Host networking is recommended: all services listen on all interfaces, and the Touch-N-Stars mDNS advertisement lets the Touch-N-Stars app discover the container on your LAN like a Raspberry Pi. With bridge networking, publish the ports listed below with -p; discovery then does not work.
Save this as docker-compose.yml, then run docker compose up -d:
services:
pins:
image: aduffeck/pins:latest
container_name: pins
restart: unless-stopped
# Time for a clean shutdown: pins disconnects the equipment and writes its
# settings, PHD2 is asked to close and flush its configuration. The
# compose default of 10 s can cut that short and lose settings.
stop_grace_period: 90s
# Host networking exposes 4782 (core), 1888 (ninaAPI), 5000 (Touch-N-Stars),
# 7624 (indiserver), 4400 (PHD2) and 8000 (pinsdaemon) directly and lets
# mDNS/Alpaca/INDI discovery reach the LAN.
network_mode: host
environment:
TZ: Europe/Berlin
# Start PHD2 (on the virtual X display) together with the container.
PHD2_AUTOSTART: "true"
# pinsdaemon management API on port 8000.
PINSDAEMON_AUTOSTART: "true"
# Bearer token expected by pinsdaemon; the image default matches the
# token shipped in the pinsdaemon Debian package.
# PINSDAEMON_API_TOKEN: "change-me"
volumes:
# Settings, profiles, logs, plugins, PHD2/INDI/driver configs, ASTAP
# databases and the sky map cache: everything under the container's
# home directory, kept in ./data/home on the host.
- ./data/home:/home/pins
# Captured images (the default image folder of a pins profile).
- ./data/images:/home/pins/Documents/N.I.N.A
# USB cameras, filter wheels, focusers: a bind mount (not a `devices:`
# entry) so that devices plugged in after the container started are
# visible too.
- /dev/bus/usb:/dev/bus/usb
# Serial mounts and accessories that are present at start. Uncomment and
# adjust; compose refuses to start if a listed device does not exist.
# devices:
# - /dev/ttyUSB0:/dev/ttyUSB0
# Grants access to the USB device nodes; the image makes the nodes of
# known astronomy vendors accessible to the unprivileged pins user.
privileged: true
docker compose up -d # start
docker compose logs -f # watch the startup
docker compose down # stop (waits up to 90 s for a clean shutdown)
docker compose pull && docker compose up -d # update to the newest image
Your data stays in ./data/home and ./data/images across updates and re-creation of the container. Files are owned by UID/GID 1000 (the pins user inside the container).
Plate solving with ASTAP needs a star database. It is not part of the image because of its size; download it once into the data volume:
docker exec pins pins-install-astap-db d50
d50 (about 860 MB) is the usual choice. Other databases:
| ID | Download size | Use |
|---|---|---|
d05 | ~100 MB | wide fields, small download |
d20 | ~380 MB | medium fields |
d50 | ~860 MB | the general-purpose database, recommended |
d80 | larger | narrow fields, long focal lengths |
g05 | Gaia-based alternative to d05 | |
w08 | very wide fields (magnitude 8) |
Several IDs can be given at once (pins-install-astap-db d05 d50). Which one fits your field of view is described on the ASTAP star database page.
The databases land in /home/pins/.local/share/astap on the volume (./data/home/.local/share/astap with the compose file above), so they survive container updates. /opt/astap and /usr/share/astap/data inside the container point there, so ASTAP finds them without further configuration. The star database installer in Touch-N-Stars (through pinsdaemon) stores its downloads in the same place, so you can use either way.
ASTAP is preconfigured as the plate solver in pins with /usr/local/bin/astap_cli.
The framing assistant and sky atlas can work offline with the N.I.N.A. sky map cache (about 3.5 GB download):
docker exec pins pins-download-skymap
It is stored in /home/pins/.local/share/NINA/FramingAssistantCache on the volume.
| Port | Service |
|---|---|
| 5000 | Touch-N-Stars web UI |
| 1888 | ninaAPI (REST/WebSocket, http://<host>:1888/v2/api/version) |
| 4782 | pins core (SignalR hubs) |
| 7624 | indiserver |
| 4400 | PHD2 server API |
| 8000 | pinsdaemon management API (http://<host>:8000/health) |
Everything that must survive lives under /home/pins, which is declared as a volume:
| Path in the container | Content |
|---|---|
/home/pins/.local/share/NINA | Profiles, logs, database, plugins, sky map cache |
/home/pins/.config | .NET user settings (ninaAPI/Touch-N-Stars plugin settings) |
/home/pins/Documents/N.I.N.A | Default image output folder |
/home/pins/.phd2 | PHD2 profiles and settings |
/home/pins/.local/share/astap | ASTAP star databases |
Some settings (plugin and application settings, PHD2 configuration) are only written on shutdown, so stop the container cleanly: docker stop -t 90 pins, or stop_grace_period: 90s in compose. docker kill or a power cut loses the settings changed since the last save.
The services run as the unprivileged pins user. For cameras, filter wheels and focusers:
/dev/bus/usb (as in the examples above) rather than passing devices with --device, so that a camera powered on after the container started is visible too.--privileged (or a device_cgroup_rules entry for character major 189).0666 on the device nodes of known astronomy vendors at start and on hotplug, so no udev rules are needed on the host./sys/module/usbcore/parameters/usbfs_memory_mb should be at least 200 (usbcore.usbfs_memory_mb=256 on the kernel command line makes it permanent).--device /dev/ttyUSB0; for serial hotplug bind-mount /dev instead.INDI drivers and PHD2 run inside the container and use the same devices.
| Variable | Default | Purpose |
|---|---|---|
TZ | UTC | Time zone of the container |
PHD2_AUTOSTART | true | Start PHD2 with the container (it can also be started and stopped from Touch-N-Stars) |
PINSDAEMON_AUTOSTART | true | Start the pinsdaemon management API |
PINSDAEMON_API_TOKEN | token of the pinsdaemon Debian package | Bearer token pinsdaemon expects; Touch-N-Stars uses the same default |
PINS_DISPLAY | :99 | X display number of the virtual display for PHD2 |
PINS_SYNC_BUNDLED_PLUGINS | 1 | Refresh the bundled plugins in the plugin folder at start (plugins you installed yourself are left alone) |
PINS_REGISTER_INDI_DRIVERS | 1 | Register the built-in INDI 3rd-party drivers for Touch-N-Stars' driver lists |
| Tag | Platform |
|---|---|
latest | linux/amd64 |
An arm64 build for the Raspberry Pi is prepared in the Dockerfile but not published yet.
pins is licensed under the Mozilla Public License 2.0 and is not affiliated with the original N.I.N.A. authors. The image also contains INDI, PHD2, ASTAP and vendor camera SDKs under their own licenses.
Content type
Image
Digest
sha256:89214682e…
Size
896.6 MB
Last updated
5 days ago
docker pull aduffeck/pins