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:
2025-12-29 15:50:37 -06:00
commit 9a1bb3d3bc
9 changed files with 539 additions and 0 deletions

16
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

85
nginx.conf Normal file
View 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
View 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

View 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"