https://github.com/mstelz/skymmich
Sync astrophotography images from Immich, plate solve them with Astrometry.net, and enrich with searchable celestial metadata.
https://github.com/mstelz/skymmich
astrometry astrophotography image-annotation image-processing image-tagging immich plate-solving
Last synced: 3 months ago
JSON representation
Sync astrophotography images from Immich, plate solve them with Astrometry.net, and enrich with searchable celestial metadata.
- Host: GitHub
- URL: https://github.com/mstelz/skymmich
- Owner: mstelz
- License: mit
- Created: 2025-06-22T03:33:37.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2026-03-31T18:29:32.000Z (3 months ago)
- Last Synced: 2026-03-31T19:19:05.983Z (3 months ago)
- Topics: astrometry, astrophotography, image-annotation, image-processing, image-tagging, immich, plate-solving
- Language: TypeScript
- Homepage:
- Size: 20.2 MB
- Stars: 9
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
SKYMMICH
**Skymmich** is a self-hosted photo gallery and management system designed specifically for astrophotographers. Built to integrate seamlessly with your [Immich](https://immich.app/) photo library, it provides intelligent plate solving, equipment tracking, and comprehensive metadata management tailored for deep-sky imaging workflows.
Perfect for organizing, analyzing, and showcasing your astrophotography collection with full control over your data and infrastructure.
> **Disclaimer**: Skymmich is an independent project and is not affiliated with, endorsed by, or officially connected to Immich or its developers. Skymmich is a third-party application that integrates with Immich's public API.
## Features
### **Self-Hosted Image Management**
- **Immich Integration**: Seamless synchronization with your self-hosted Immich photo library
- **Interactive Sky Map**: Explore your collection on a high-fidelity celestial atlas powered by Aladin Lite v3
- **Astrophotography Filtering**: Filter by telescopes, cameras, targets, constellations, and acquisition details
- **Deep Zoom Viewer**: High-resolution exploration of your deep-sky images with OpenSeaDragon
- **Metadata Preservation**: Automatic EXIF handling for astrophotography workflows
> **Note**: XMP sidecar generation is currently experimental and may not work as intended in all configurations. Configure `IMMICH_MAPPING_PATH` and `LOCAL_MAPPING_PATH` environment variables to map Immich volume paths to local paths for sidecar file placement.
- **Zero Duplication**: View images directly from Immich without storage overhead
- **Location Editing**: Save and reuse observing sites with map picker; coordinate changes sync back to the original Immich asset automatically
### **DSO Catalog & Target Tracking**
- **Built-in OpenNGC Catalog**: Browse, search, and filter thousands of deep-sky objects by type, constellation, magnitude, and angular size
- **DSS Thumbnails**: Cached Digitized Sky Survey preview images for catalog objects
- **Target Wishlists**: Annotate catalog objects with personal notes and tags on the Targets page
- **Target Backfill**: Automatically match plate-solved images to catalog objects via the admin panel
### **Acquisition Logging**
- **Per-Filter Tracking**: Record exposure details per filter including frame count, exposure time, gain, offset, binning, and sensor temperature
- **Integration Summary**: Automatic calculation of total frames, total integration time, and filter breakdown per image
### **Plate Solving**
- **Astrometry.net Integration**: Automatic coordinate solving for your images
- **Background Processing**: Non-blocking worker processes with job queuing
- **Real-time Updates**: Live progress tracking via WebSocket connections
- **Batch Processing**: Handle multiple images simultaneously
- **Results Storage**: Persistent RA/Dec coordinates and field information
### **Astrophotography Equipment Tracking**
- **Telescope Catalog**: Manage your telescopes, mounts, and accessories with specifications
- **Camera Database**: Track sensors, filters, and imaging configurations specific to astrophotography
- **Equipment Groups**: Bundle equipment into reusable presets and apply them to images in one click
- **Session Logging**: Automatic equipment association from EXIF metadata and manual tagging
### **Admin Interface**
- **Configuration Management**: Secure API key and integration settings
- **Automated Sync**: Cron jobs automatically sync images from Immich and clean up old notifications on a configurable schedule
- **Worker Supervisor**: Background plate-solving workers automatically restart on failure with exponential backoff when Auto mode is enabled
- **Database Backup**: One-click SQLite database download from the admin panel (PostgreSQL users should use `pg_dump`)
- **Catalog Management**: Load, reload, and check for OpenNGC catalog updates; backfill target names for existing images
### **Real-Time Notifications**
- **Live Updates**: WebSocket-powered notifications for plate-solving results, Immich sync completions, and other events
- **Manual Sync**: Trigger an Immich sync at any time from the header bar
- **Notification Badge**: Unacknowledged notification count displayed in the navigation
### **Security & Deployment**
- **Docker Ready**: Multi-stage containerization with health checks
- **UnRAID Support**: Ready-to-use container templates
- **Database Options**: Built-in SQLite (default), optional PostgreSQL support
## Quick Start
> **Prerequisites**: Skymmich requires a running [Immich](https://immich.app/) instance for photo management. Ensure you have Immich set up and accessible before proceeding.
### Option 1: Docker Compose (Recommended)
Single container setup with built-in SQLite database — no external database needed:
```bash
# Download production compose file
curl -o docker-compose.prod.yml https://raw.githubusercontent.com/mstelz/Skymmich/main/docker-compose.prod.yml
# Start Skymmich
docker compose -f docker-compose.prod.yml up -d
# Access the application
open http://localhost:5000
```
**What this includes:**
- Skymmich application from GitHub Container Registry
- Built-in SQLite database with persistent storage
- Health checks and automatic restarts
- Volume mounts for configuration, logs, and database
> **PostgreSQL option**: If you prefer PostgreSQL, download [`docker-compose.postgres.yml`](docker-compose.postgres.yml) and layer it on:
> ```bash
> echo "POSTGRES_PASSWORD=your_secure_password" > .env
> docker compose -f docker-compose.prod.yml -f docker-compose.postgres.yml up -d
> ```
### Option 2: Docker Container
Single container deployment using GitHub Container Registry:
```bash
# Pull the latest image
docker pull ghcr.io/mstelz/skymmich:latest
# Run with Docker (uses built-in SQLite database)
docker run -d \
--name skymmich \
-p 5000:5000 \
-e NODE_ENV=production \
-v skymmich-config:/app/config \
-v skymmich-cache:/app/cache \
ghcr.io/mstelz/skymmich:latest
# Access the application
open http://localhost:5000
```
> To use PostgreSQL instead, add `-e DATABASE_URL="postgresql://user:password@host:5432/skymmich"` to the command above.
### Option 3: UnRAID Template
> **Coming Soon**: Skymmich will be available in UnRAID Community Applications for easy one-click installation.
For now, manual installation:
1. **Install Skymmich**: Add container using template URL `https://raw.githubusercontent.com/mstelz/Skymmich/main/docker/unraid-templates/skymmich.xml`
2. **Configure**: Optionally set Immich URL and API keys (can also be done via admin UI)
3. **Access**: Navigate to `http://your-server:2284`
> No external database needed — Skymmich uses a built-in SQLite database stored in the config directory. To use PostgreSQL instead, set the `DATABASE_URL` field in the template.
### Option 4: Development Setup
```bash
# Clone and install dependencies
git clone https://github.com/mstelz/Skymmich.git
cd Skymmich
npm install
# Option A: Build and run with Docker Compose (builds from source)
# Edit docker-compose.yml environment section with your settings
docker compose up -d
# Option B: Local development server
cp .env.example .env.local
# Edit .env.local with your development settings (uses SQLite by default)
npm run dev
# Option C: Worker-only deployment (standalone)
cp .env.worker.example .env.worker
# Edit .env.worker with database and API settings
npm run dev:worker:standalone
# Access at http://localhost:5000 (Docker) or http://localhost:5173 (local)
```
## Requirements
### Core Requirements
- **Immich Server**: Self-hosted photo management server (currently the only supported photo source)
- **Docker**: 20.10+ (for containerized deployment)
- **Database**: Built-in SQLite (default, no setup required). PostgreSQL 15+ optionally supported.
- Automatic schema management with Drizzle ORM
- Migration script included for moving data between SQLite and PostgreSQL (see [Docker docs](docker/README.md#migrating-between-sqlite-and-postgresql))
### Development Requirements
- **Node.js**: 20+ (for building from source)
### Optional Integrations
- **Astrometry.net API Key**: For automated plate solving capabilities
> **Note**: Support for additional photo sources beyond Immich is planned for future releases, but Immich is currently required as the primary photo library.
## Configuration
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | _(empty)_ | Optional PostgreSQL connection string. Leave empty to use built-in SQLite. |
| `PORT` | `5000` | HTTP server port |
| `NODE_ENV` | `development` | Application environment |
| `IMMICH_URL` | _(optional)_ | Immich server base URL |
| `IMMICH_API_KEY` | _(optional)_ | Immich API authentication key |
| `ASTROMETRY_API_KEY` | _(optional)_ | Astrometry.net API key |
| `ENABLE_PLATE_SOLVING` | `true` | Enable background worker |
| `PLATE_SOLVE_MAX_CONCURRENT` | `3` | Max simultaneous jobs |
| `XMP_SIDECAR_PATH` | `/app/sidecars` | Directory for XMP sidecar files |
### Admin Configuration
After startup, access the admin interface at `/admin` to configure:
- **Immich Integration**: Server URL, API keys, album picker, sync schedules
- **Astrometry Settings**: API credentials, job limits, auto-processing
- **Worker Management**: Enable/disable background processing
- **Sync Scheduling**: Automated Immich synchronization frequency
> **Tip**: Configuration via admin interface takes precedence over environment variables and persists across container restarts.
## Database Migration
Skymmich includes a bidirectional migration script for moving data between SQLite and PostgreSQL:
```bash
# PostgreSQL → SQLite
node tools/scripts/migrate-db.js \
--from postgresql://user:pass@host:5432/skymmich \
--to sqlite:path/to/skymmich.db
# SQLite → PostgreSQL
node tools/scripts/migrate-db.js \
--from sqlite:path/to/local.db \
--to postgresql://user:pass@host:5432/skymmich
```
Inside a Docker container:
```bash
node /app/dist/tools/scripts/migrate-db.js \
--from postgresql://... \
--to sqlite:/app/config/skymmich.db
```
To avoid running the command manually inside the container, set the `AUTO_DB_MIGRATE_FROM` environment variable (and optional `AUTO_DB_MIGRATE_TO`) on the Skymmich service. The Docker startup script runs the migration before launching the app, deletes any existing SQLite target file (unless `AUTO_DB_MIGRATE_RESET_SQLITE=false`), and writes a marker to `/app/config/.auto-db-migrated` so it only happens once unless you delete that file or set `AUTO_DB_MIGRATE_ONCE=false`.
The script handles all type conversions (timestamps, booleans, JSON, arrays) and respects foreign key ordering automatically. SQLite targets run the bundled Drizzle migrations during the copy; PostgreSQL targets should be initialized once beforehand so the schema exists.
## Container Images
Skymmich provides ready-to-use container images through GitHub Container Registry:
### Available Images
- **Latest Release**: `ghcr.io/mstelz/skymmich:latest`
- **Specific Version**: `ghcr.io/mstelz/skymmich:v1.x.x`
- **Development**: `ghcr.io/mstelz/skymmich:main`
### Supported Architectures
- `linux/amd64` (x86_64)
- `linux/arm64` (ARM64/Apple Silicon)
### Image Tags
- `latest` - Latest stable release
- `v*.*.*` - Semantic version tags (e.g., `v1.0.0`)
- `main` - Latest development build from main branch
- `sha-*` - Specific commit builds
All images are automatically built, tested, and scanned for vulnerabilities using GitHub Actions.
## Architecture
```
┌─────────────────────────────────────┐
│ Skymmich Container │
├─────────────────────────────────────┤
│ Frontend (React + TypeScript) │
│ ├─ Vite build system │ ┌─────────────────────┐
│ ├─ Tailwind CSS + shadcn/ui │ │ External APIs │
│ └─ Real-time WebSocket client │ ├─────────────────────┤
├─────────────────────────────────────┤◄──►│ Immich Server │
│ Backend (Hono + Node.js) │ │ Astrometry.net │
│ ├─ RESTful API endpoints │ │ Image Sources │
│ ├─ WebSocket server (ws) │ └─────────────────────┘
│ ├─ Image proxy & thumbnails │
│ └─ Session management │ ┌─────────────────────┐
├─────────────────────────────────────┤ │ PostgreSQL │
│ Worker Manager │ │ (optional) │
│ ├─ Background job processing │◄──►│ External database │
│ ├─ Plate solving automation │ │ for advanced use │
│ ├─ Crash recovery & monitoring │ └─────────────────────┘
│ └─ Graceful shutdown handling │
├─────────────────────────────────────┤
│ SQLite (built-in, default) │
│ └─ /app/config/skymmich.db │
└─────────────────────────────────────┘
```
## Project Structure
```
Skymmich/
├── apps/
│ ├── client/ # React frontend application
│ │ ├── src/
│ │ │ ├── components/ # UI components (shadcn/ui)
│ │ │ ├── pages/ # Route components
│ │ │ ├── lib/ # Utilities and API clients
│ │ │ └── hooks/ # Custom React hooks
│ │ └── dist/ # Built frontend assets
│ └── server/ # Node.js backend application
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ ├── services/ # Business logic services
│ │ ├── workers/ # Background job processors
│ │ └── db.ts # Database configuration
│ └── dist/ # Compiled backend code
├── packages/
│ └── shared/ # Shared types and schemas
│ ├── src/
│ │ ├── db/ # Database schemas (SQLite/PostgreSQL)
│ │ ├── schemas/ # Zod validation schemas
│ │ └── types/ # TypeScript type definitions
├── docker/ # Containerization files
│ ├── Dockerfile # Multi-stage container build
│ ├── docker-compose.yml # Service orchestration
│ ├── startup.sh # Container entry point
│ └── unraid-templates/ # UnRAID deployment templates
├── tools/ # Development and migration tools
│ ├── scripts/ # Utility scripts
│ └── migrations/ # Database migration files
├── docs/ # Documentation
└── assets/ # Static assets and examples
```
## Development
### Prerequisites
```bash
# Install Node.js 20+
node --version # v20+
npm --version # 10+
# Clone repository
git clone https://github.com/mstelz/Skymmich.git
cd Skymmich
```
### Setup
```bash
# Install dependencies
npm install
# Setup environment (choose one based on your needs)
cp .env.example .env.local # Main application settings
cp .env.worker.example .env.worker # Worker-only deployment
# Configure your development settings
# Database schema is managed automatically on startup via Drizzle ORM
```
### Development Commands
```bash
# Start development server (SQLite database by default)
npm run dev # Full stack: server + frontend + worker
npm run dev:server:watch # Server only with file watching
npm run dev:worker # Worker process only
npm run dev:worker:standalone # Standalone worker (uses .env.worker)
# Build for production
npm run build # Build frontend and backend
npm run build:docker # Build with Docker assets
# Docker development (uses SQLite by default)
docker compose up -d # Full stack via Docker
```
### Testing
Skymmich includes comprehensive end-to-end testing using Playwright:
```bash
# Run all tests
npm run test:e2e # Run Playwright end-to-end tests
# Interactive testing
npm run test:e2e:ui # Run tests with Playwright UI mode
npm run test:e2e:debug # Debug tests with Playwright inspector
npm run test:e2e:headed # Run tests in headed browser mode
```
**Test Structure:**
- `tests/e2e/` - End-to-end test specifications
- `tests/e2e/pages/` - Page Object Model classes for maintainable tests
- `playwright.config.ts` - Playwright configuration with multiple browsers
**Prerequisites for Testing:**
- Skymmich application running on `http://localhost:5173`
- Test database with sample data
- All dependencies installed via `npm install`
### Code Quality
```bash
# Type checking
npm run check # TypeScript compilation check
```
## CI/CD & Deployment
Skymmich uses GitHub Actions for continuous integration and deployment. All builds are automatically tested, scanned for vulnerabilities, and containerized.
### Automated Workflows
- **Build & Push**: Automatic Docker image builds on main branch commits
- **PR Testing**: Validates all pull requests with build tests and security scans
- **Release**: Semantic versioning releases with tagged Docker images
### Security
- All images are scanned with Trivy for vulnerabilities
- Critical vulnerabilities block deployments
- SBOM (Software Bill of Materials) generated for each build
For detailed CI/CD documentation, see [docs/CI_CD.md](docs/CI_CD.md).
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## Roadmap
### Core Features
- [ ] **Additional Photo Sources**: Support for photo libraries beyond Immich (direct uploads, other self-hosted solutions)
- [x] **Interactive Sky Map**: Celestial atlas visualization for plate-solved image collections
- [ ] Advanced image statistics and analytics for astrophotography sessions
- [ ] Equipment usage reporting and session tracking
- [x] XMP sidecar generation for astrophotography metadata
- [ ] XMP sidecar viewer and editor for astrophotography metadata
### Integrations
- [ ] **NINA Plugin**: Sync session data (targets, equipment, acquisition details) directly from N.I.N.A. to Skymmich
- [ ] **Local Plate Solving**: Integration with local solvers (ASTAP, PixInsight) for offline solving without Astrometry.net
### Advanced Features
- [ ] Advanced search and filtering with saved queries
- [ ] Bulk image processing workflows and batch operations
- [ ] View saved/tagged targets on the Sky Map
- [ ] Raw data and calibration frame management
- [ ] Mobile app companion for field use
- [ ] Community features (sharing, public galleries)
### Community & Help
- **Bug Reports**: [GitHub Issues](https://github.com/mstelz/Skymmich/issues)
- **Feature Requests**: [GitHub Discussions](https://github.com/mstelz/Skymmich/discussions)
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Acknowledgments
- **[Immich](https://immich.app/)** - Inspiration and integration for photo management
- **[Astrometry.net](https://astrometry.net/)** - Plate solving service and algorithms
- **[shadcn/ui](https://ui.shadcn.com/)** - Beautiful and accessible React components
- **[Drizzle ORM](https://orm.drizzle.team/)** - Type-safe database toolkit
---
**Built for the astrophotography community**
[Star this repo](https://github.com/mstelz/Skymmich) | [Report bug](https://github.com/mstelz/Skymmich/issues) | [Request feature](https://github.com/mstelz/Skymmich/discussions)