feat: add miniPaint stack (paint.pivoine.art)
Added new paint service stack to the docker-compose infrastructure: - **Paint stack** (paint.pivoine.art): - miniPaint: Web-based image editor built from GitHub - Multi-stage Docker build clones from https://github.com/viliusle/miniPaint - Features: layers, filters, drawing tools, text, shapes support - Client-side processing with no server uploads - Stateless architecture (no backups needed) Infrastructure updates: - Created paint/compose.yaml with Traefik routing and SSL - Created paint/Dockerfile with Node.js build stage and nginx serve - Added PAINT environment variables to arty.yml - Updated compose.yaml include list - Updated CLAUDE.md documentation All services integrated with Traefik for SSL termination and include Watchtower auto-update labels. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
22
CLAUDE.md
22
CLAUDE.md
@@ -23,6 +23,7 @@ Root `compose.yaml` uses Docker Compose's `include` directive to orchestrate mul
|
||||
- **vault**: Vaultwarden password manager (SQLite)
|
||||
- **joplin**: Joplin Server note-taking and sync platform (PostgreSQL)
|
||||
- **vert**: VERT file format converter (WebAssembly-based, stateless)
|
||||
- **paint**: miniPaint web-based image editor (built from GitHub)
|
||||
- **restic**: Backrest backup system with restic backend
|
||||
- **sablier**: Dynamic scaling plugin for Traefik
|
||||
- **vpn**: WireGuard VPN (wg-easy)
|
||||
@@ -272,6 +273,27 @@ Simply access https://vert.pivoine.art and drag/drop files to convert between fo
|
||||
|
||||
**Note**: VERT is stateless and doesn't require backups as no data is persisted.
|
||||
|
||||
### Paint (paint/compose.yaml)
|
||||
miniPaint web-based image editor built from GitHub:
|
||||
- **paint**: miniPaint app exposed at `paint.pivoine.art:80`
|
||||
- Online image editor with layer support
|
||||
- Built directly from https://github.com/viliusle/miniPaint
|
||||
- Supports PNG, JPG, GIF, WebP formats
|
||||
- Features: layers, filters, drawing tools, text, shapes
|
||||
- Client-side processing (no uploads to server)
|
||||
- No persistent data storage required
|
||||
- Stateless architecture
|
||||
|
||||
**Build Process**:
|
||||
- Multi-stage Docker build clones from GitHub
|
||||
- Builds using Node.js 18
|
||||
- Serves static files via nginx
|
||||
|
||||
**Usage**:
|
||||
Access https://paint.pivoine.art to use the image editor. All editing happens in the browser - images are not uploaded to the server.
|
||||
|
||||
**Note**: miniPaint is stateless and doesn't require backups as no data is persisted.
|
||||
|
||||
### Restic (restic/compose.yaml)
|
||||
Backrest backup system with restic backend:
|
||||
- **backrest**: Backrest web UI exposed at `restic.pivoine.art:9898`
|
||||
|
||||
4
arty.yml
4
arty.yml
@@ -116,6 +116,10 @@ envs:
|
||||
VERT_IMAGE: ghcr.io/vert-sh/vert:latest
|
||||
VERT_TRAEFIK_HOST: vert.pivoine.art
|
||||
VERT_SABLIER_ENABLED: true
|
||||
# Paint
|
||||
PAINT_TRAEFIK_ENABLED: true
|
||||
PAINT_COMPOSE_PROJECT_NAME: paint
|
||||
PAINT_TRAEFIK_HOST: paint.pivoine.art
|
||||
# Proxy
|
||||
PROXY_COMPOSE_PROJECT_NAME: proxy
|
||||
PROXY_DOCKER_IMAGE: traefik:latest
|
||||
|
||||
@@ -11,6 +11,7 @@ include:
|
||||
- vault/compose.yaml
|
||||
- joplin/compose.yaml
|
||||
- vert/compose.yaml
|
||||
- paint/compose.yaml
|
||||
- restic/compose.yaml
|
||||
- umami/compose.yaml
|
||||
- sablier/compose.yaml
|
||||
|
||||
23
paint/Dockerfile
Normal file
23
paint/Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
||||
# Build miniPaint from GitHub repository
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Clone the repository
|
||||
RUN apk add --no-cache git && \
|
||||
git clone https://github.com/viliusle/miniPaint.git . && \
|
||||
npm install && \
|
||||
npm run build
|
||||
|
||||
# Production stage with nginx
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy built files from builder
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
# Copy nginx configuration if needed
|
||||
COPY --from=builder /app /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
32
paint/compose.yaml
Normal file
32
paint/compose.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
paint:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: minipaint:latest
|
||||
container_name: ${PAINT_COMPOSE_PROJECT_NAME}_app
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- compose_network
|
||||
labels:
|
||||
- 'traefik.enable=${PAINT_TRAEFIK_ENABLED}'
|
||||
# HTTP to HTTPS redirect
|
||||
- 'traefik.http.middlewares.${PAINT_COMPOSE_PROJECT_NAME}-redirect-web-secure.redirectscheme.scheme=https'
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web.middlewares=${PAINT_COMPOSE_PROJECT_NAME}-redirect-web-secure'
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web.rule=Host(`${PAINT_TRAEFIK_HOST}`)'
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web.entrypoints=web'
|
||||
# HTTPS router
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web-secure.rule=Host(`${PAINT_TRAEFIK_HOST}`)'
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web-secure.tls.certresolver=resolver'
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web-secure.entrypoints=web-secure'
|
||||
- 'traefik.http.routers.${PAINT_COMPOSE_PROJECT_NAME}-web-secure.middlewares=security-headers@file'
|
||||
# Service
|
||||
- 'traefik.http.services.${PAINT_COMPOSE_PROJECT_NAME}-web-secure.loadbalancer.server.port=80'
|
||||
- 'traefik.docker.network=${NETWORK_NAME}'
|
||||
# Watchtower
|
||||
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
|
||||
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
Reference in New Issue
Block a user