A Flask-based astrophotography web application
Project description
AstroSpace
AstroSpace is a Flask application for hosting and organizing astrophotography posts on your own infrastructure. It combines image publishing, equipment tracking, plate-solving overlays, and guiding-log visualization in one self-hosted site.
You can see a public instance here: astro.space-js.de
Preferred Docker Deployment
The preferred way to run AstroSpace in production is with nginx/docker-compose.yml. That stack starts:
astrospace_app: the published AstroSpace image, which runs Gunicorn on internal port9000astrospace_nginx: the public entrypoint, which listens on port8181, serves static/uploaded files directly, and proxies app requests toastrospace_app
PostgreSQL is intentionally not included in this compose file. AstroSpace expects an existing database server, and you provide its connection details through environment variables.
How Compose Settings Work
nginx/docker-compose.yml uses ${...} placeholders for runtime settings. The simplest setup is:
cd nginx- create a
.envfile next todocker-compose.yml - run
docker compose ...from thatnginx/directory
Example nginx/.env:
SECRET_KEY=change-me
DB_NAME=astrospace
DB_USER=astrospace
DB_PASSWORD=change-me
DB_HOST=192.168.1.20
DB_PORT=5432
TITLE=AstroSpace
MAX_USERS=2
What each setting is for:
SECRET_KEY: Flask session and CSRF signing key. Set this to a long random value.DB_NAME: PostgreSQL database name AstroSpace should use.DB_USER: PostgreSQL username.DB_PASSWORD: PostgreSQL password.DB_HOST: hostname or IP address of your PostgreSQL server. This is usually another machine or another container stack.DB_PORT: PostgreSQL port, usually5432.TITLE: site title shown in the UI.MAX_USERS: maximum allowed registered users.
UPLOAD_PATH is already fixed inside the compose file as /uploads. That path must match the mounted uploads volume, so you normally do not override it in .env.
Volume Mounts And Purpose
The bind mounts in nginx/docker-compose.yml are important because both the app and nginx need access to specific files on the host:
/mnt/user/AstroSpaceUploads:/uploadsThis is the persistent data directory for uploaded preview images, thumbnails, FITS/XISF files, generated overlays, starless variants, and other user media. This path must survive container recreation./mnt/user/Astro/_web_/AstroSpace/AstroSpace/static:/staticThis exposes AstroSpace static assets to nginx so/static/...can be served directly instead of going through Flask. Keep this host directory in sync with the AstroSpace version you deploy./mnt/user/Astro/_web_/AstroSpace/nginx/nginx.conf:/etc/nginx/nginx.conf:roThis mounts the nginx configuration file into the nginx container as read-only.
Before first start, edit the host-side paths in nginx/docker-compose.yml so they match your machine. The left side of each mount is your host path; the right side is the fixed path used inside the container.
What nginx.conf Does
nginx/nginx.conf is the reverse-proxy layer in front of AstroSpace:
- listens on port
8181 - serves
/uploads/directly from the mounted uploads folder - serves
/static/directly from the mounted static folder - proxies all other requests to
http://astrospace_app:9000/ - forwards the original
Hostheader and visitor IP viaX-Real-IP - raises
client_max_body_sizeto2000Mso large astrophotography uploads are accepted - increases proxy/read/send timeouts so long-running requests are less likely to be cut off early
In short: nginx handles public HTTP traffic and file serving, while the AstroSpace app container focuses on Flask/Gunicorn.
Commands To Run
Use these commands from nginx/:
docker compose pull
docker compose run --rm astrospace_app migrate
docker compose up -d
What each command does:
docker compose pullDownloads the image versions referenced by the compose file.docker compose run --rm astrospace_app migrateRuns Alembic migrations before the web stack starts. On compatible older AstroSpace databases, this also auto-stamps the legacy schema before applying newer revisions.docker compose up -dStarts the app and nginx containers in the background.
Useful follow-up commands:
docker compose logs -f astrospace_app astrospace_nginx
docker compose down
After startup, open http://YOUR_HOST:8181.
For updates, the normal sequence is the same:
docker compose pull
docker compose run --rm astrospace_app migrate
docker compose up -d
If you prefer to pin a specific image version instead of latest, change the image: line in nginx/docker-compose.yml to a concrete tag such as sharonshaji92/astrospace:1.3.8.
Features
- User registration with a configurable user limit
- Rich post creation for astrophotography images and acquisition details
- Equipment inventory management for telescopes, cameras, filters, and accessories
- FITS/XISF-assisted plate solving and generated overlays
- PHD2 guiding log parsing and Plotly-based visualizations
- Public collection pages and per-image detail views
- Docker-friendly deployment
- Optional opt-in debug logging for local development and container runs
Requirements
- Python 3.11+
- PostgreSQL
- Optional: Node.js if you want to rebuild Tailwind CSS assets
- Optional: Docker for containerized deployment
Quick Start
Local install
python -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -e .[dev]
Configuration
AstroSpace reads configuration from:
- environment variables
- the file pointed to by
ASTROSPACE_SETTINGS instance/config.py
Required settings:
SECRET_KEYDB_NAMEDB_USERDB_PASSWORDDB_HOSTDB_PORTUPLOAD_PATH
Common optional settings:
TITLEMAX_USERSSESSION_COOKIE_SECURE
Example config file:
SECRET_KEY = "change-me"
DB_NAME = "astrospace"
DB_USER = "astrospace"
DB_PASSWORD = "change-me"
DB_HOST = "localhost"
DB_PORT = 5432
UPLOAD_PATH = r"C:\astrospace\uploads"
TITLE = "My AstroSpace"
MAX_USERS = 2
Run locally
Run migrations first:
python -m AstroSpace migrate
set ASTROSPACE_SETTINGS=path\to\config.py
flask --app AstroSpace run
The app starts on http://127.0.0.1:5000 by default.
If you are upgrading an existing pre-Alembic AstroSpace database, this is usually enough:
python -m AstroSpace migrate
migrate will auto-stamp a compatible legacy AstroSpace schema before applying newer revisions. The explicit stamp command is still available if you want to control that step yourself:
python -m AstroSpace stamp
python -m AstroSpace migrate
Debug Logging
AstroSpace includes opt-in runtime logging around the places most likely to block or fail: app startup, database bootstrapping, post creation, inventory updates, plate solving, and guide-log parsing.
Enable it in either of these ways:
flask --app AstroSpace run --debug
set ASTROSPACE_DEBUG=1
flask --app AstroSpace run
For the Docker image, append --debug to the container command or set ASTROSPACE_DEBUG=1.
Manual Docker
Build the image locally:
docker build -t astrospace .
Run it:
docker run --rm ^
-e SECRET_KEY=change-me ^
-e DB_NAME=astrospace ^
-e DB_USER=astrospace ^
-e DB_PASSWORD=change-me ^
-e DB_HOST=host.docker.internal ^
-e DB_PORT=5432 ^
-e UPLOAD_PATH=/uploads ^
-v C:\astrospace\uploads:/uploads ^
astrospace migrate
Then start the web container:
docker run ^
--name astrospace ^
-p 9000:9000 ^
-e SECRET_KEY=change-me ^
-e DB_NAME=astrospace ^
-e DB_USER=astrospace ^
-e DB_PASSWORD=change-me ^
-e DB_HOST=host.docker.internal ^
-e DB_PORT=5432 ^
-e TITLE=AstroSpace ^
-e MAX_USERS=2 ^
-e UPLOAD_PATH=/uploads ^
-v C:\astrospace\uploads:/uploads ^
astrospace
Run the same container in debug mode:
docker run ^
--name astrospace-debug ^
-p 9000:9000 ^
-e SECRET_KEY=change-me ^
-e DB_NAME=astrospace ^
-e DB_USER=astrospace ^
-e DB_PASSWORD=change-me ^
-e DB_HOST=host.docker.internal ^
-e DB_PORT=5432 ^
-e TITLE=AstroSpace ^
-e MAX_USERS=2 ^
-e UPLOAD_PATH=/uploads ^
-e ASTROSPACE_DEBUG=1 ^
-v C:\astrospace\uploads:/uploads ^
astrospace --debug
The image starts Gunicorn on 0.0.0.0:9000.
Development
Run the test suite:
python -m pytest -q
If you update Tailwind sources:
cd AstroSpace
npm install
npx tailwindcss -i ./static/input.css -o ./static/styles.css
Useful first-run steps:
- Register the first user. The first account becomes admin.
- Open
My Profileand configure the site title and welcome message. - Create a new post with a preview image and optional FITS/XISF metadata.
- Add or normalize inventory entries from the profile page if needed.
Release Workflow
Build and publish a wheel with Hatch:
python -m pip install hatch
python -m hatch build -t wheel
python -m hatch publish
Project Layout
AstroSpace/: application packagedocs/: project documentationtests/: automated testsnginx/: example reverse-proxy and compose assets
License
This project is licensed under the GNU GPL-3.0 License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file astrospace-1.3.8-py3-none-any.whl.
File metadata
- Download URL: astrospace-1.3.8-py3-none-any.whl
- Upload date:
- Size: 6.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.3 cpython/3.12.10 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0299aa557a599c8a00972f248f2ca46a28850cc27650ec0140e69418b9ae2dba
|
|
| MD5 |
27fe8aabc5526269f5a864ebcbe3953d
|
|
| BLAKE2b-256 |
36d167a9cbb33915dfc8c98f05c38b99d223f136269b2682ca683f386cbbce9b
|