Initial Blinko Cloudron package
- CloudronManifest.json with PostgreSQL and localstorage addons - Dockerfile based on cloudron/base:5.0.0 - NGINX reverse proxy configuration - Supervisor process management - Initialization script with auto-configuration
This commit is contained in:
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Cloudron build artifacts
|
||||
.cloudronbuild/
|
||||
|
||||
# Editor files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
149
BUILD.md
Normal file
149
BUILD.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Blinko Cloudron Package - Build Instructions
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Cloudron CLI installed (`npm install -g cloudron`)
|
||||
- Docker installed
|
||||
- Access to build service: `builder.docker.due.ren`
|
||||
- Build service token configured
|
||||
|
||||
## Package Structure
|
||||
|
||||
```
|
||||
blink-cloudron/
|
||||
├── CloudronManifest.json # Cloudron app manifest
|
||||
├── Dockerfile # Container build definition
|
||||
├── start.sh # Initialization and startup script
|
||||
├── nginx.conf # NGINX reverse proxy configuration
|
||||
├── supervisor/
|
||||
│ └── supervisord.conf # Process management configuration
|
||||
├── logo.png # App icon (required)
|
||||
└── BUILD.md # This file
|
||||
```
|
||||
|
||||
## Configuration Details
|
||||
|
||||
### Application
|
||||
|
||||
- **App ID**: `io.blinko.cloudronapp`
|
||||
- **Internal Port**: 1111 (Blinko Node.js server)
|
||||
- **External Port**: 8000 (NGINX proxy)
|
||||
- **Memory Limit**: 512MB
|
||||
|
||||
### Addons
|
||||
|
||||
- **PostgreSQL**: Database storage for notes and user data
|
||||
- **Local Storage**: Persistent file storage at `/app/data`
|
||||
|
||||
### Environment Variables (Auto-configured)
|
||||
|
||||
| Variable | Source | Description |
|
||||
|----------|--------|-------------|
|
||||
| `DATABASE_URL` | `CLOUDRON_POSTGRESQL_URL` | PostgreSQL connection string |
|
||||
| `NEXTAUTH_URL` | `CLOUDRON_APP_ORIGIN` | Application URL for authentication |
|
||||
| `NEXT_PUBLIC_BASE_URL` | `CLOUDRON_APP_ORIGIN` | Public-facing URL |
|
||||
| `NEXTAUTH_SECRET` | Auto-generated | Session encryption key |
|
||||
| `NODE_ENV` | `production` | Runtime environment |
|
||||
| `TRUST_PROXY` | `1` | Trust reverse proxy headers |
|
||||
|
||||
## Build Commands
|
||||
|
||||
### 1. Get the logo
|
||||
|
||||
Download or create a `logo.png` file (256x256 recommended):
|
||||
|
||||
```bash
|
||||
# Download from Blinko repository
|
||||
curl -o logo.png https://raw.githubusercontent.com/blinkospace/blinko/main/public/logo.svg
|
||||
# Convert to PNG if needed (requires ImageMagick)
|
||||
# convert logo.svg -resize 256x256 logo.png
|
||||
```
|
||||
|
||||
### 2. Build the package
|
||||
|
||||
```bash
|
||||
cloudron build \
|
||||
--set-build-service builder.docker.due.ren \
|
||||
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
|
||||
--set-repository andreasdueren/blinko-cloudron \
|
||||
--tag 1.0.0
|
||||
```
|
||||
|
||||
### 3. Install the package
|
||||
|
||||
```bash
|
||||
cloudron install \
|
||||
--location blinko.due.ren \
|
||||
--image andreasdueren/blinko-cloudron:1.0.0
|
||||
```
|
||||
|
||||
### 4. View logs during installation
|
||||
|
||||
```bash
|
||||
cloudron logs --app blinko.due.ren -f
|
||||
```
|
||||
|
||||
**Important**: Don't wait more than 30 seconds for installation feedback. If there's an error, the install command may hang indefinitely.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check application logs
|
||||
|
||||
```bash
|
||||
cloudron logs --app blinko.due.ren -f
|
||||
```
|
||||
|
||||
### Shell into the container
|
||||
|
||||
```bash
|
||||
cloudron exec --app blinko.due.ren
|
||||
```
|
||||
|
||||
### Common issues
|
||||
|
||||
1. **Database connection fails**
|
||||
- Check PostgreSQL addon is properly configured
|
||||
- Verify `DATABASE_URL` environment variable
|
||||
|
||||
2. **Authentication issues**
|
||||
- Ensure `NEXTAUTH_URL` matches the app domain
|
||||
- Check that `NEXTAUTH_SECRET` was generated
|
||||
|
||||
3. **Static files not loading**
|
||||
- Verify NGINX is running: `supervisorctl status`
|
||||
- Check NGINX logs for errors
|
||||
|
||||
4. **Memory issues**
|
||||
- Increase `memoryLimit` in CloudronManifest.json if needed
|
||||
- Monitor with: `cloudron status --app blinko.due.ren`
|
||||
|
||||
### Rebuild after changes
|
||||
|
||||
Always uninstall and reinstall fresh during development:
|
||||
|
||||
```bash
|
||||
cloudron uninstall --app blinko.due.ren
|
||||
cloudron build --set-build-service builder.docker.due.ren \
|
||||
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
|
||||
--set-repository andreasdueren/blinko-cloudron \
|
||||
--tag 1.0.1
|
||||
cloudron install --location blinko.due.ren --image andreasdueren/blinko-cloudron:1.0.1
|
||||
```
|
||||
|
||||
## Data Persistence
|
||||
|
||||
All persistent data is stored in `/app/data`:
|
||||
|
||||
- `/app/data/.blinko` - Application data directory
|
||||
- `/app/data/.nextauth_secret` - Authentication secret
|
||||
- `/app/data/.initialized` - First-run marker
|
||||
|
||||
This directory is automatically backed up by Cloudron.
|
||||
|
||||
## References
|
||||
|
||||
- [Blinko Documentation](https://blinko.mintlify.app/)
|
||||
- [Blinko GitHub](https://github.com/blinkospace/blinko)
|
||||
- [Cloudron Packaging Guide](https://docs.cloudron.io/packaging/tutorial/)
|
||||
- [Cloudron Manifest Reference](https://docs.cloudron.io/packaging/manifest/)
|
||||
- [Cloudron Addons](https://docs.cloudron.io/packaging/addons/)
|
||||
30
CloudronManifest.json
Normal file
30
CloudronManifest.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"id": "io.blinko.cloudronapp",
|
||||
"title": "Blinko",
|
||||
"author": "Blinko Space",
|
||||
"description": "AI-powered card note-taking application for capturing fleeting thoughts with RAG-enhanced search, markdown support, and self-hosted privacy.",
|
||||
"tagline": "AI-powered note-taking",
|
||||
"version": "1.0.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 8000,
|
||||
"addons": {
|
||||
"postgresql": {},
|
||||
"localstorage": {}
|
||||
},
|
||||
"manifestVersion": 2,
|
||||
"website": "https://blinko.mintlify.app/",
|
||||
"contactEmail": "support@blinko.space",
|
||||
"icon": "file://logo.png",
|
||||
"tags": [
|
||||
"notes",
|
||||
"ai",
|
||||
"productivity",
|
||||
"markdown"
|
||||
],
|
||||
"memoryLimit": 512000000,
|
||||
"minBoxVersion": "7.0.0",
|
||||
"postInstallMessage": "Blinko has been installed successfully!\n\nVisit your Blinko instance to create your first account.\nThe first user to register will become the administrator.\n\nData is stored in /app/data and will be backed up automatically.",
|
||||
"changelog": {
|
||||
"1.0.0": "Initial Cloudron package"
|
||||
}
|
||||
}
|
||||
67
Dockerfile
Normal file
67
Dockerfile
Normal file
@@ -0,0 +1,67 @@
|
||||
FROM cloudron/base:5.0.0
|
||||
|
||||
# Install Bun for building
|
||||
RUN curl -fsSL https://bun.sh/install | bash
|
||||
ENV PATH="/root/.bun/bin:${PATH}"
|
||||
|
||||
# Set up working directory
|
||||
WORKDIR /app/code
|
||||
|
||||
# Clone Blinko repository
|
||||
ARG BLINKO_VERSION=main
|
||||
RUN git clone --depth 1 --branch ${BLINKO_VERSION} https://github.com/blinkospace/blinko.git /tmp/blinko
|
||||
|
||||
# Build the application
|
||||
WORKDIR /tmp/blinko
|
||||
|
||||
# Install dependencies with Bun
|
||||
RUN bun install --frozen-lockfile
|
||||
|
||||
# Handle Sharp for native image processing
|
||||
RUN ARCH=$(uname -m) && \
|
||||
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then \
|
||||
bun add sharp@0.34.1 --arch=arm64 --platform=linux; \
|
||||
fi
|
||||
|
||||
# Generate Prisma client
|
||||
RUN bunx prisma generate
|
||||
|
||||
# Build the application
|
||||
RUN bun run build:web
|
||||
RUN bun run build:seed
|
||||
|
||||
# Copy built application to /app/code
|
||||
WORKDIR /app/code
|
||||
RUN cp -r /tmp/blinko/dist /app/code/dist && \
|
||||
cp -r /tmp/blinko/server /app/code/server && \
|
||||
cp -r /tmp/blinko/prisma /app/code/prisma && \
|
||||
cp -r /tmp/blinko/node_modules /app/code/node_modules && \
|
||||
cp /tmp/blinko/package.json /app/code/package.json
|
||||
|
||||
# Copy public assets if they exist
|
||||
RUN if [ -d /tmp/blinko/public ]; then cp -r /tmp/blinko/public /app/code/public; fi
|
||||
|
||||
# Set up initial data directory template
|
||||
RUN mkdir -p /tmp/data/.blinko
|
||||
|
||||
# Install dumb-init
|
||||
RUN ARCH=$(uname -m) && \
|
||||
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then \
|
||||
DUMB_INIT_ARCH="aarch64"; \
|
||||
else \
|
||||
DUMB_INIT_ARCH="x86_64"; \
|
||||
fi && \
|
||||
curl -Lo /usr/local/bin/dumb-init "https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_${DUMB_INIT_ARCH}" && \
|
||||
chmod +x /usr/local/bin/dumb-init
|
||||
|
||||
# Clean up
|
||||
RUN rm -rf /tmp/blinko
|
||||
|
||||
# Copy Cloudron configuration files
|
||||
COPY start.sh /app/code/start.sh
|
||||
COPY nginx.conf /app/code/nginx.conf
|
||||
COPY supervisor/ /app/code/supervisor/
|
||||
|
||||
RUN chmod +x /app/code/start.sh
|
||||
|
||||
CMD ["/app/code/start.sh"]
|
||||
93
NOTES.md
Normal file
93
NOTES.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Blinko Cloudron Package - Development Notes
|
||||
|
||||
## Application Summary
|
||||
|
||||
**Blinko** is an AI-powered card note-taking application with:
|
||||
- RAG (Retrieval-Augmented Generation) for natural language search
|
||||
- Markdown support
|
||||
- Self-hosted, privacy-focused design
|
||||
- PostgreSQL database backend
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Frontend**: React, Next.js
|
||||
- **Backend**: Node.js, Express
|
||||
- **Database**: PostgreSQL 14+
|
||||
- **ORM**: Prisma
|
||||
- **Build Tool**: Bun
|
||||
- **Runtime Port**: 1111
|
||||
|
||||
## Key Environment Variables
|
||||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
| `DATABASE_URL` | PostgreSQL connection string |
|
||||
| `NEXTAUTH_URL` | App URL for NextAuth.js |
|
||||
| `NEXT_PUBLIC_BASE_URL` | Public-facing URL |
|
||||
| `NEXTAUTH_SECRET` | Session encryption secret |
|
||||
| `TRUST_PROXY` | Enable when behind reverse proxy |
|
||||
| `TZ` | Timezone setting |
|
||||
|
||||
## Cloudron Integration
|
||||
|
||||
### Addons Used
|
||||
- `postgresql` - Database storage
|
||||
- `localstorage` - Persistent file storage
|
||||
|
||||
### Port Mapping
|
||||
- NGINX listens on port 8000 (Cloudron httpPort)
|
||||
- Proxies to Blinko on port 1111
|
||||
|
||||
### Data Directories
|
||||
- `/app/data/.blinko` - Application files
|
||||
- `/app/data/.nextauth_secret` - Auth secret (generated on first run)
|
||||
- `/app/data/.initialized` - First-run marker
|
||||
|
||||
## Build Commands Quick Reference
|
||||
|
||||
```bash
|
||||
# Build
|
||||
cloudron build \
|
||||
--set-build-service builder.docker.due.ren \
|
||||
--build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \
|
||||
--set-repository andreasdueren/blinko-cloudron \
|
||||
--tag VERSION
|
||||
|
||||
# Install
|
||||
cloudron install \
|
||||
--location blinko.due.ren \
|
||||
--image andreasdueren/blinko-cloudron:VERSION
|
||||
|
||||
# Uninstall (for fresh install during development)
|
||||
cloudron uninstall --app blinko.due.ren
|
||||
|
||||
# Logs
|
||||
cloudron logs --app blinko.due.ren -f
|
||||
|
||||
# Shell access
|
||||
cloudron exec --app blinko.due.ren
|
||||
```
|
||||
|
||||
## Files in Package
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `CloudronManifest.json` | App metadata, addons, ports |
|
||||
| `Dockerfile` | Build instructions |
|
||||
| `start.sh` | Initialization and startup |
|
||||
| `nginx.conf` | Reverse proxy config |
|
||||
| `supervisor/supervisord.conf` | Process management |
|
||||
| `logo.png` | App icon (needs to be added) |
|
||||
|
||||
## Known Considerations
|
||||
|
||||
1. **First user becomes admin** - The first account registered gets admin privileges
|
||||
2. **Memory usage** - Set to 512MB, may need adjustment for heavy use
|
||||
3. **AI features** - Require additional configuration (OpenAI API key, etc.)
|
||||
4. **File uploads** - 50MB limit configured in NGINX
|
||||
|
||||
## Upstream Resources
|
||||
|
||||
- GitHub: https://github.com/blinkospace/blinko
|
||||
- Docs: https://blinko.mintlify.app/
|
||||
- Docker: https://hub.docker.com/r/blinkospace/blinko
|
||||
85
nginx.conf
Normal file
85
nginx.conf
Normal file
@@ -0,0 +1,85 @@
|
||||
daemon off;
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
error_log stderr;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
access_log /dev/stdout;
|
||||
error_log stderr;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
client_max_body_size 50M;
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss text/javascript application/x-javascript image/svg+xml;
|
||||
|
||||
upstream blinko {
|
||||
server 127.0.0.1:1111;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8000;
|
||||
server_name _;
|
||||
|
||||
# Health check endpoint
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 'OK';
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# Proxy all requests to Blinko
|
||||
location / {
|
||||
proxy_pass http://blinko;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
|
||||
# WebSocket support
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
|
||||
# Timeouts for long-running requests
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# Static files with caching
|
||||
location /_next/static/ {
|
||||
proxy_pass http://blinko;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
expires 7d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
}
|
||||
61
start.sh
Normal file
61
start.sh
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
echo "=> Starting Blinko for Cloudron"
|
||||
|
||||
# Initialize data directory on first run
|
||||
if [[ ! -f /app/data/.initialized ]]; then
|
||||
echo "=> First run: initializing data directory..."
|
||||
mkdir -p /app/data/.blinko
|
||||
touch /app/data/.initialized
|
||||
fi
|
||||
|
||||
# Generate NEXTAUTH_SECRET if not present
|
||||
if [[ ! -f /app/data/.nextauth_secret ]]; then
|
||||
echo "=> Generating NEXTAUTH_SECRET..."
|
||||
openssl rand -base64 32 > /app/data/.nextauth_secret
|
||||
fi
|
||||
|
||||
NEXTAUTH_SECRET=$(cat /app/data/.nextauth_secret)
|
||||
|
||||
# Set ownership
|
||||
chown -R cloudron:cloudron /app/data
|
||||
|
||||
# Configure environment from Cloudron
|
||||
export NODE_ENV=production
|
||||
export DATABASE_URL="${CLOUDRON_POSTGRESQL_URL}"
|
||||
export NEXTAUTH_URL="${CLOUDRON_APP_ORIGIN}"
|
||||
export NEXT_PUBLIC_BASE_URL="${CLOUDRON_APP_ORIGIN}"
|
||||
export NEXTAUTH_SECRET="${NEXTAUTH_SECRET}"
|
||||
export TRUST_PROXY=1
|
||||
export DISABLE_SECURE_COOKIE=false
|
||||
|
||||
# Configure mail settings if available
|
||||
if [[ -n "${CLOUDRON_MAIL_SMTP_SERVER:-}" ]]; then
|
||||
export SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER}"
|
||||
export SMTP_PORT="${CLOUDRON_MAIL_SMTP_PORT}"
|
||||
export SMTP_USER="${CLOUDRON_MAIL_SMTP_USERNAME}"
|
||||
export SMTP_PASS="${CLOUDRON_MAIL_SMTP_PASSWORD}"
|
||||
export SMTP_FROM="${CLOUDRON_MAIL_FROM}"
|
||||
fi
|
||||
|
||||
# Set timezone if configured
|
||||
export TZ="${TZ:-UTC}"
|
||||
|
||||
# Link data directory for Blinko
|
||||
ln -sfn /app/data/.blinko /app/code/.blinko
|
||||
|
||||
# Run database migrations
|
||||
echo "=> Running database migrations..."
|
||||
cd /app/code
|
||||
npx prisma migrate deploy --schema=/app/code/prisma/schema.prisma
|
||||
|
||||
# Seed database if needed
|
||||
echo "=> Checking database seed..."
|
||||
node /app/code/server/seed.js 2>/dev/null || true
|
||||
|
||||
# Configure NGINX
|
||||
cp /app/code/nginx.conf /run/nginx.conf
|
||||
|
||||
echo "=> Starting supervisor..."
|
||||
exec /usr/bin/supervisord --configuration /app/code/supervisor/supervisord.conf --nodaemon
|
||||
38
supervisor/supervisord.conf
Normal file
38
supervisor/supervisord.conf
Normal file
@@ -0,0 +1,38 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
pidfile=/run/supervisord.pid
|
||||
|
||||
[unix_http_server]
|
||||
file=/run/supervisor.sock
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///run/supervisor.sock
|
||||
|
||||
[program:nginx]
|
||||
command=/usr/sbin/nginx -c /run/nginx.conf
|
||||
directory=/app/code
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
priority=10
|
||||
|
||||
[program:blinko]
|
||||
command=/usr/local/bin/dumb-init node /app/code/server/index.js
|
||||
directory=/app/code
|
||||
user=cloudron
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
priority=20
|
||||
environment=NODE_ENV="production",HOME="/app/data"
|
||||
Reference in New Issue
Block a user