AI 资讯
Building VS — 2026-06-23
Here's a thinking process: Analyze User Input: Role: Ghostwriter for Roberto Luna Osorio Editorial Profile: Developer Storytelling (primary), Build in Public, Técnico, Reflexivo. Philosophy: Share the process/learnings, not just the perfect result. Mandatory narrative questions: Problem, First attempt, What went wrong, How solved, What learned, What's next. Tone: First person, direct, honest, technical but accessible, curious. Avoid corporate jargon, clickbait, marketing hype, false modesty, empty summaries. Language: Spanish (natural/colloquial tech MX/LatAm) OR English (conversational, dev-friendly). Wait, the prompt says "English only (Dev.to is primarily English)" for this specific article. I'll stick to English as instructed for the Dev.to angle. Angle: TECHNICAL DEEP-DIVE ("HOW I BUILT IT"). Focus on code, architecture, specific files. Different from Medium's narrative style. Style: Technical, precise, code-forward. Real file/function names, error messages. First person but engineer-voice. English only. Mandatory Structure: TL;DR, The Problem, What I Tried First, The Implementation, Key Takeaway, What's Next. Length: 800-1200 words. Tags: #vibecoding #buildinpublic + relevant tech tags. Input Data: Repo: VS, Date: 2026-06-23. Commits show v1.6.0 sprint 1, booking reminders, /confirm/:token, notifications, bulk actions, pipeline v2. Files modified: booking-reminders.service.ts , booking.controller.ts , email.cron.ts , notifications.controller.ts , NotificationBell.tsx , confirm/[token]/page.tsx , ventas/pipeline/page.tsx , etc. Diffs show version bumps, cron integration, notification controller refactor, new components. Constraint: Do NOT repeat angles from this week: "El control de acceso y la caja negra de las publicaciones". Choose a completely different angle. Final Instruction: Write complete article. Start directly with TL;DR. Include actual code snippets. Do NOT write a story — write a technical breakdown. Map to Editorial Profile & Constraints: Profile
开发者
How I Automated DigitalOcean Infrastructure with SuperPlane
Our infrastructure "documentation" was a Google Sheet. Anyone on the team could edit it. Nobody...
AI 资讯
Fixing “Git Divergent Branches” on a Production Server (Real DevOps Debugging Walkthrough)
One of the most confusing errors you can face while deploying a Node.js or Docker-based application is: fatal: Need to specify how to reconcile divergent branches At first glance, it looks like a Git bug. In reality, it is Git doing exactly what it should do, protecting you from overwriting history. In this article, I’ll break down a real production incident where a deployment failed due to divergent Git branches, how we diagnosed it, and the correct DevOps fix. The Problem A simple deployment script was running: git pull docker compose down --remove-orphans docker compose up --build -d But it failed with: fatal: Need to specify how to reconcile divergent branches This stopped deployment completely. What Git Was Telling Us To understand the issue, we ran: git rev-list --left-right --count HEAD...origin/main Output: 1 16 This means: 1 commit exists locally on the server 16 commits exist on GitHub So the branches had diverged. Why This Happens (Important) This usually happens when: Someone runs git commit directly on a server A previous deployment used git pull with merge commits History between local and remote is no longer linear Git refuses to guess whether you want to: Merge Rebase Or reject changes So it throws an error. Deep Diagnosis We inspected the commits: git log --oneline origin/main..HEAD Result: 6d9046b Merge pull request #222 Then: git log --oneline HEAD..origin/main Showed multiple new GitHub PR merges. Conclusion: The server was behind GitHub The “local commit” was already part of repo history No real production changes existed on server The Real Fix (Production Safe) For deployment servers, you should NEVER rely on git pull . Instead, use a deterministic reset: git fetch origin git reset --hard origin/main Then redeploy: docker compose down --remove-orphans docker compose up --build -d Why This Works This approach ensures: Server always matches GitHub exactly No merge conflicts in production No accidental local commits survive Fully reproducible depl
AI 资讯
Deploying Zabbix Open-Source Monitoring Platform on Ubuntu 24.04
Zabbix is an open-source monitoring platform that tracks the health and performance of servers, networks, applications, and services, with built-in alerting and visualisation. This guide deploys the Zabbix server, web UI, agent, and MySQL database using Docker Compose, with Traefik handling automatic HTTPS for the dashboard. By the end, you'll have Zabbix monitoring its own host with a secured dashboard at your domain. Set Up the Project Directory 1. Create the project directory: $ mkdir ~/zabbix-docker $ cd ~/zabbix-docker 2. Create the environment file: $ nano .env DOMAIN = zabbix.example.com LETSENCRYPT_EMAIL = admin@example.com MYSQL_PASSWORD = YOUR_DB_PASSWORD MYSQL_ROOT_PASSWORD = YOUR_ROOT_PASSWORD Deploy with Docker Compose 1. Add your user to the Docker group: $ sudo usermod -aG docker $USER $ newgrp docker 2. Create the Compose manifest: $ nano docker-compose.yaml services : traefik : image : traefik:v3.6 container_name : traefik restart : unless-stopped command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entrypoint.to=websecure" - " --entrypoints.web.http.redirections.entrypoint.scheme=https" - " --certificatesresolvers.le.acme.httpchallenge=true" - " --certificatesresolvers.le.acme.httpchallenge.entrypoint=web" - " --certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}" - " --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json" ports : - " 80:80" - " 443:443" volumes : - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt networks : - zabbix-net mysql-server : image : mysql:8.4.8 container_name : zabbix-mysql environment : MYSQL_DATABASE : zabbix MYSQL_USER : zabbix MYSQL_PASSWORD : ${MYSQL_PASSWORD} MYSQL_ROOT_PASSWORD : ${MYSQL_ROOT_PASSWORD} volumes : - ./mysql-data:/var/lib/mysql networks : - zabbix-net restart : unless-stopped zabbix-server : image : zabbix/zabbix-se
AI 资讯
Deploying SeaweedFS, an Open-Source S3 Storage Alternative to MinIO, on Ubuntu 24.04
SeaweedFS is an open-source, distributed object storage system with an S3-compatible API, a filer for POSIX-style hierarchical access, and a small footprint. This guide deploys SeaweedFS using Docker Compose with the master, volume, filer, S3, and admin services behind Traefik for automatic HTTPS on separate admin and S3 domains. By the end, you'll have SeaweedFS serving S3-compatible object storage securely at your domains. Prerequisite: Two DNS A records pointing at the server — storage.example.com (admin dashboard) and s3.storage.example.com (S3 API). AWS CLI installed on your local machine for testing. Set Up the Directory Structure 1. Create the project directory: $ mkdir seaweedfs && cd seaweedfs 2. Generate an access key and a secret key (run twice and save both): $ openssl rand -hex 16 3. Create the environment file: $ nano .env STORAGE_DOMAIN = storage.example.com LETSENCRYPT_EMAIL = your-email@example.com ADMIN_PASSWORD = yourpassword 4. Create the S3 identities file: $ nano s3-config.json { "identities" : [ { "name" : "admin" , "credentials" : [ { "accessKey" : "YOUR_ACCESS_KEY" , "secretKey" : "YOUR_SECRET_KEY" } ], "actions" : [ "Admin" , "Read" , "Write" , "List" , "Tagging" ] } ] } Deploy with Docker Compose 1. Create the Compose manifest: $ nano docker-compose.yml services : traefik : image : traefik:v3.7.0 container_name : traefik restart : unless-stopped ports : - " 80:80" - " 443:443" volumes : - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt command : - --providers.docker=true - --providers.docker.exposedByDefault=false - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.web.http.redirections.entrypoint.scheme=https - --entrypoints.web.http.redirections.entrypoint.permanent=true - --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL} - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json - --
AI 资讯
Deploying Qdrant Open-Source Vector Database for AI Applications on Ubuntu 24.04
Qdrant is an open-source vector database for AI applications, optimised for similarity search over high-dimensional embeddings, with a REST/gRPC API, payload filtering, and a built-in dashboard. This guide deploys Qdrant using Docker Compose with Traefik handling automatic HTTPS, API-key authentication, and a sample collection that runs a similarity search. By the end, you'll have Qdrant serving vector search securely at your domain. Set Up the Directory Structure 1. Create the project directory: $ mkdir -p ~/qdrant/data $ cd ~/qdrant 2. Generate a strong API key: $ openssl rand -hex 32 Save the value for the .env file. 3. Create the environment file: $ nano .env DOMAIN = qdrant.example.com LETSENCRYPT_EMAIL = admin@example.com QDRANT_API_KEY = PASTE_GENERATED_KEY_HERE Deploy with Docker Compose 1. Create the Compose manifest: $ nano docker-compose.yaml services : traefik : image : traefik:v3.6 container_name : traefik command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --api.dashboard=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entrypoint.to=websecure" - " --entrypoints.web.http.redirections.entrypoint.scheme=https" - " --certificatesresolvers.letsencrypt.acme.httpchallenge=true" - " --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - " --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}" - " --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" ports : - " 80:80" - " 443:443" volumes : - " ./letsencrypt:/letsencrypt" - " /var/run/docker.sock:/var/run/docker.sock:ro" restart : unless-stopped qdrant : image : qdrant/qdrant:v1.17.1 container_name : qdrant expose : - " 6333" volumes : - " ./data:/qdrant/storage" environment : QDRANT__SERVICE__API_KEY : " ${QDRANT_API_KEY}" labels : - " traefik.enable=true" - " traefik.http.routers.qdrant.rule=Host(`${DOMAIN}`)" - " traefik.http.routers.qdrant.entr
AI 资讯
Deploying Paperless-ngx Open-Source Document Management System on Ubuntu 24.04
Paperless-ngx is an open-source document management system that converts scans and PDFs into a fully searchable archive using Tesseract OCR, with tags, custom fields, and automated processing rules. This guide deploys Paperless-ngx using Docker Compose with PostgreSQL, Redis, and Traefik handling automatic HTTPS, then uploads a document and verifies OCR extraction. By the end, you'll have Paperless-ngx serving an OCR-indexed document archive securely at your domain. Set Up the Directory Structure 1. Create the project directories: $ mkdir -p ~/paperless-ngx/ { data,media,export,consume,pgdata } $ cd ~/paperless-ngx 2. Create the environment file: $ nano .env DOMAIN = paperless.example.com LETSENCRYPT_EMAIL = admin@example.com PAPERLESS_SECRET_KEY = CHANGE_TO_RANDOM_STRING PAPERLESS_URL = https://paperless.example.com PAPERLESS_TIME_ZONE = UTC PAPERLESS_OCR_LANGUAGE = eng PAPERLESS_DBPASS = STRONG_PASSWORD_HERE POSTGRES_DB = paperless POSTGRES_USER = paperless POSTGRES_PASSWORD = STRONG_PASSWORD_HERE Use the same value for PAPERLESS_DBPASS and POSTGRES_PASSWORD . PAPERLESS_SECRET_KEY should be a 32+ character random string. Deploy with Docker Compose 1. Create the Compose manifest: $ nano docker-compose.yaml services : traefik : image : traefik:v3.6 container_name : traefik command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entrypoint.to=websecure" - " --entrypoints.web.http.redirections.entrypoint.scheme=https" - " --certificatesresolvers.letsencrypt.acme.httpchallenge=true" - " --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - " --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}" - " --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" ports : - " 80:80" - " 443:443" volumes : - " ./letsencrypt:/letsencrypt" - " /var/run/docker.sock:/var/run/docker.sock:ro"
AI 资讯
Deploying Overleaf Open-Source LaTeX Collaboration Platform on Ubuntu 24.04
Overleaf is an open-source, collaborative LaTeX editor that bundles MongoDB, Redis, and the ShareLaTeX application into a single self-hosted stack. This guide deploys Overleaf Community Edition using the official Toolkit plus a Traefik override that adds automatic HTTPS via Let's Encrypt. By the end, you'll have Overleaf serving collaborative LaTeX editing securely at your domain. Set Up the Project Directory 1. Clone the Overleaf Toolkit: $ git clone https://github.com/overleaf/toolkit.git ~/overleaf-toolkit $ cd ~/overleaf-toolkit 2. Initialize the configuration: $ bin/init This creates config/overleaf.rc , config/variables.env , and config/version . 3. Create a directory for Traefik file-provider routes: $ mkdir traefik-routes Configure Overleaf for a Reverse Proxy 1. Edit config/variables.env : $ nano config/variables.env OVERLEAF_APP_NAME = "My Overleaf Instance" OVERLEAF_SITE_URL = https://overleaf.example.com OVERLEAF_NAV_TITLE = "Overleaf CE" OVERLEAF_BEHIND_PROXY = true OVERLEAF_SECURE_COOKIE = true The last two flags are required when Overleaf is fronted by an HTTPS reverse proxy. 2. Edit config/overleaf.rc : $ nano config/overleaf.rc SIBLING_CONTAINERS_ENABLED = false 3. Create the project-level .env file used by the Traefik Compose file: $ nano .env DOMAIN = overleaf.example.com LETSENCRYPT_EMAIL = admin@example.com SERVER_IP = 192.0.2.1 SERVER_IP should be the server's public IP (Traefik binds 80/443 to it). Add the Traefik Route 1. Create the dynamic route: $ nano traefik-routes/overleaf.yml http : routers : overleaf : rule : " Host(`overleaf.example.com`)" service : overleaf entryPoints : - websecure tls : certResolver : le services : overleaf : loadBalancer : servers : - url : " http://sharelatex:80" 2. Create the Traefik Compose file: $ nano docker-compose.traefik.yml services : traefik : image : traefik:v3.6 container_name : traefik restart : unless-stopped command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --
AI 资讯
Deploying Ory Kratos Open-Source Identity and User Management System on Ubuntu 24.04
Ory Kratos is an open-source, API-first identity and user management system handling registration, login, recovery, verification, and session management with a self-service UI. This guide deploys Kratos using Docker Compose with PostgreSQL, the self-service UI Node, and Traefik handling automatic HTTPS for the public API. By the end, you'll have Kratos managing identities and sessions for users registering through your domain over HTTPS. Prerequisite: SMTP credentials are required for verification and recovery emails. The admin API stays bound to 127.0.0.1 on purpose — never expose it publicly. Set Up the Directory Structure 1. Create the project directories: $ mkdir -p ~/ory-kratos/ { config,data/postgres } $ cd ~/ory-kratos 2. Create the environment file: $ nano .env DOMAIN = kratos.example.com LETSENCRYPT_EMAIL = admin@example.com KRATOS_VERSION = v26.2.0 POSTGRES_USER = kratos POSTGRES_PASSWORD = EXAMPLE_DB_PASSWORD POSTGRES_DB = kratosdb LOG_LEVEL = info 3. Create the identity schema — defines the user fields (email + name) and how the email maps to login, recovery, and verification: $ nano config/identity.schema.json Use the schema described in the Vultr Docs walkthrough — email is the login identifier with password auth; name is a free-text trait. 4. Create the Kratos configuration — public/admin API URLs, password policy (12-char minimum + HaveIBeenPwned), session lifetimes, self-service flows, SMTP courier: $ nano config/kratos.yml Fill in the full configuration from the source article. Key points to keep consistent with the stack below: Public API listens on the internal port and is fronted by Traefik on ${DOMAIN} . Admin API listens on 127.0.0.1:4434 only — used by tooling on the host. The DSN points at the postgres service ( postgres://kratos:...@postgres:5432/kratosdb?sslmode=disable ). The courier section uses your SMTP provider for verification mail. Deploy with Docker Compose 1. Create the Compose manifest: $ nano docker-compose.yml services : traefi
AI 资讯
Deploying NocoDB Open-Source Airtable Alternative on Ubuntu 24.04
NocoDB is an open-source no-code platform that puts a spreadsheet-style UI on top of a relational database, with grid, form, Kanban, and gallery views plus a REST API. This guide deploys NocoDB using Docker Compose with a PostgreSQL backend and Traefik handling automatic HTTPS, then exercises the API with a sample base. By the end, you'll have NocoDB serving a base over HTTPS with API access at your domain. Set Up the Directory Structure 1. Create the project directories: $ mkdir -p ~/nocodb/ { data,pgdata,letsencrypt } $ cd ~/nocodb 2. Create the environment file: $ nano .env DOMAIN = nocodb.example.com LETSENCRYPT_EMAIL = admin@example.com POSTGRES_DB = postgres POSTGRES_PASSWORD = strong_password POSTGRES_USER = postgres Deploy with Docker Compose 1. Create the Compose manifest: $ nano docker-compose.yaml services : traefik : image : traefik:v3.6 container_name : traefik command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entrypoint.to=websecure" - " --entrypoints.web.http.redirections.entrypoint.scheme=https" - " --certificatesresolvers.letsencrypt.acme.httpchallenge=true" - " --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - " --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}" - " --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" ports : - " 80:80" - " 443:443" volumes : - " ./letsencrypt:/letsencrypt" - " /var/run/docker.sock:/var/run/docker.sock:ro" restart : unless-stopped db : image : postgres:16 container_name : nocodb-db hostname : root_db environment : POSTGRES_DB : ${POSTGRES_DB} POSTGRES_USER : ${POSTGRES_USER} POSTGRES_PASSWORD : ${POSTGRES_PASSWORD} volumes : - " ./pgdata:/var/lib/postgresql/data" healthcheck : test : [ " CMD" , " pg_isready" , " -U" , " ${POSTGRES_USER}" , " -d" , " ${POSTGRES_DB}" ] interval : 10s timeout : 5s retries :
AI 资讯
Deploying MLflow Open-Source Machine Learning Experiment Tracking on Ubuntu 24.04
MLflow is an open-source platform for managing the machine learning lifecycle — experiment tracking, model registry, and reproducible runs. This guide deploys MLflow using Docker Compose with a PostgreSQL backend, S3-compatible artifact storage, basic-auth, and Traefik handling automatic HTTPS, then logs a sample scikit-learn run. By the end, you'll have MLflow recording experiments at your domain over HTTPS. Prerequisite: An S3-compatible bucket (e.g. Vultr Object Storage) with access key, secret key, region, and endpoint URL. Set Up the Directory Structure 1. Create the project directory: $ mkdir -p ~/mlflow $ cd ~/mlflow 2. Create the environment file: $ nano .env DOMAIN = mlflow.example.com LETSENCRYPT_EMAIL = admin@example.com POSTGRES_USER = mlflow POSTGRES_PASSWORD = StrongDatabasePassword123 MLFLOW_AUTH_CONFIG_PATH = /app/basic_auth.ini MLFLOW_FLASK_SERVER_SECRET_KEY = GENERATED_SECRET_KEY S3_BUCKET = mlflow-artifacts S3_ACCESS_KEY = YOUR_ACCESS_KEY S3_SECRET_KEY = YOUR_SECRET_KEY S3_REGION = YOUR_REGION S3_ENDPOINT = https://YOUR_OBJECT_STORAGE_ENDPOINT 3. Create the basic-auth configuration: $ nano basic_auth.ini [mlflow] default_permission = READ database_uri = sqlite:///basic_auth.db admin_username = admin admin_password = ADMIN_PASSWORD authorization_function = mlflow.server.auth:authenticate_request_basic_auth 4. Create a Dockerfile that adds the auth-server extras and Postgres/S3 clients to the official image: $ nano Dockerfile FROM ghcr.io/mlflow/mlflow:v3.10.1 RUN pip install --no-cache-dir psycopg2-binary boto3 'mlflow[auth]' Deploy with Docker Compose 1. Create the Compose manifest: $ nano docker-compose.yml services : traefik : image : traefik:v3.6 container_name : traefik command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entrypoint.to=websecure" - " --entrypoints.web.http.redirections.entrypoint
AI 资讯
Deploying LocalAI Self-Hosted AI Model Management Platform on Ubuntu 24.04
LocalAI is an open-source platform for running Large Language Models locally with an OpenAI-compatible API, so you can swap it in behind existing OpenAI client code without paying per-token or sending data off-server. This guide deploys LocalAI using Docker Compose with Traefik handling automatic HTTPS, persistent model and cache directories, and a working chat-completion test. By the end, you'll have LocalAI serving an OpenAI-compatible API securely at your domain. Set Up the Directory Structure 1. Create the project directories: $ mkdir -p ~/localai/ { models,cache } $ cd ~/localai models/ holds downloaded model files; cache/ persists between restarts. 2. Create the environment file: $ nano .env DOMAIN = localai.example.com LETSENCRYPT_EMAIL = admin@example.com Deploy with Docker Compose 1. Add your user to the Docker group: $ sudo usermod -aG docker $USER $ newgrp docker 2. Create the Compose manifest: $ nano docker-compose.yaml services : traefik : image : traefik:v3.6 container_name : traefik restart : unless-stopped environment : DOCKER_API_VERSION : " 1.44" command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entrypoint.to=websecure" - " --entrypoints.web.http.redirections.entrypoint.scheme=https" - " --certificatesresolvers.le.acme.httpchallenge=true" - " --certificatesresolvers.le.acme.httpchallenge.entrypoint=web" - " --certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}" - " --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json" ports : - " 80:80" - " 443:443" volumes : - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt localai : image : localai/localai:latest-aio-cpu container_name : localai restart : unless-stopped volumes : - ./models:/models:cached - ./cache:/cache:cached healthcheck : test : [ " CMD" , " curl" , " -f" , " http://localhost:8080/readyz" ] interval :
AI 资讯
Deploying LibreChat Open-Source AI Chat Platform on Ubuntu 24.04
LibreChat is an open-source, ChatGPT-style web UI that supports OpenAI, Anthropic, Azure OpenAI, Gemini, OpenRouter, local OpenAI-compatible endpoints, and more — with MongoDB-backed conversation history and Meilisearch-powered search. This guide deploys LibreChat using its official Compose manifest plus a Traefik override for automatic HTTPS. By the end, you'll have LibreChat running with a registration page and multi-provider chat at your domain over HTTPS. Clone LibreChat and Prepare the Environment 1. Clone the LibreChat repository and check out a stable tag: $ git clone https://github.com/danny-avila/LibreChat.git $ cd LibreChat $ git checkout tags/v0.8.3 2. Find the Meilisearch data directory name pinned by this release: $ grep -o 'meili_data_v[0-9.]*' docker-compose.yml | head -1 3. Create the required data directories (replace meili_data_v1.35.1 if the previous command printed a different name): $ mkdir -p data-node images logs meili_data_v1.35.1 uploads $ sudo chown -R 1000:1000 meili_data_v1.35.1 4. Copy the env template and uncomment the UID/GID lines: $ cp .env.example .env $ nano .env UID = 1000 GID = 1000 Override the Compose Stack with Traefik 1. Create a Compose override that adds Traefik and wires the API to it: $ nano docker-compose.override.yml services : api : labels : - " traefik.enable=true" - " traefik.http.routers.librechat.rule=Host(`librechat.example.com`)" - " traefik.http.routers.librechat.entrypoints=websecure" - " traefik.http.routers.librechat.tls.certresolver=leresolver" - " traefik.http.services.librechat.loadbalancer.server.port=3080" volumes : - ./librechat.yaml:/app/librechat.yaml traefik : image : traefik:v3.6.10 ports : - " 80:80" - " 443:443" volumes : - " /var/run/docker.sock:/var/run/docker.sock:ro" - " ./letsencrypt:/letsencrypt" command : - " --providers.docker=true" - " --providers.docker.exposedbydefault=false" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirect
AI 资讯
Dev Log: 2026-06-23 — Query Cleanups, Real Health Checks, Safer MCP Tools, and Password-Reset Plumbing
A wide day rather than a deep one — four separate threads across a few projects, each with a lesson worth keeping. I'll teach the patterns and keep the specifics generic. The through-line: make the system honest about what it's actually doing — which queries it fires, whether a service is really up, what a tool will do when you call it twice, and in what order a password change should land. The performance thread got big enough that I split it into its own focused post; here's the short version plus the three other threads. Thread 1 — Stop paying for queries you don't use A sustained sweep through an app (and the package behind it) hunting wasted database work. The highlights: Arm an N+1 detector in dev only. A query detector wired in behind an environment check turns invisible lazy-loads into a visible to-do list. Never in production — it's a developer aid, not a runtime guard. Unused eager loads are N+1s in disguise. Index screens love to with(['creator', 'approver']) for columns a redesign later removed. Not a loop, but the same disease: queries you hydrate and throw away. Delete the eager loads with no consumer in the view. Memoize per-request constants. A default-connection resolver and a sidebar unread count were both recomputed on every call. ??= once, reuse for the rest of the request. Collapse a dashboard's stat queries. ~20 count() calls became one grouped query per table, wrapped in a short-lived cache. A dashboard can tolerate being a few seconds stale; trade live-to-the-second for cheap. The meta-lesson: performance at this layer is mostly removal , and you lock it in with a Pest query-count assertion so nobody quietly re-adds an N+1 six months later. Full write-up in the focused post. Thread 2 — Health checks that actually check Here's a trap I keep seeing in "is it up?" tooling: the check verifies the record exists, or that a config row is present, and calls it green. That's not a health check — that's a config check. The service can be configured per
AI 资讯
Dev Log: 2026-06-22 — Configurable Schedulers, Load-Test Toolkits, and an MCP Server
Some days the work spreads across a few projects instead of landing as one big feature. Today was that — three distinct threads, each with a lesson worth keeping. I'll keep things generic and teach the pattern rather than the project, but the through-line is the same: move things that were hardcoded or ephemeral into something you can configure, repeat, and trust. Thread 1 — Make scheduled tasks configurable instead of code-only If you've run a Laravel app for any length of time, you know the scheduler lives in code: routes/console.php or the kernel, a wall of ->daily() , ->everyFiveMinutes() , ->cron(...) . That's fine until the day an operator — not a developer — needs to change when something runs. Then you're shipping a deploy just to nudge a cron expression. Silly. Today's work pulled scheduler configuration into a settings-backed UI. The pattern is worth stealing: instead of the schedule being a literal in code, the code reads its cadence from a settings store, and there's an admin screen to edit it. // Instead of a hardcoded cadence... $schedule -> command ( 'subscriptions:reconcile' ) -> daily (); // ...read it from settings, with a sane default baked in. $schedule -> command ( 'subscriptions:reconcile' ) -> cron ( $this -> schedulerSettings -> reconcileCron ?? '0 2 * * *' ); Two things made this clean. First, a SchedulerSettings object (Spatie's settings pattern) so the values are typed, cached, and migratable — not loose rows you Setting::get('...') by string key. Second, grouping the more user-facing schedules behind their own modal rather than dumping every cron in one giant form. A subscription-related schedule belongs next to subscriptions; a platform schedule belongs in admin. Same data, but organized by who needs to touch it . The edge case to watch: a UI-editable cron is a foot-gun if you let people type nonsense. Validate the expression on save, and always keep a default so a blank setting can never silently disable a job. Thread 2 — A load-testing
AI 资讯
Presentation: The Time It Wasn't DNS
Sean Klein discusses why "human error" is a dangerous myth in complex systems. Sharing the inside story of Azure’s 2023 global WAN outage, he explains how modern incident analysis looks past the "Five Whys" to uncover systemic issues. Learn how engineering leaders can move away from blame, improve Standard Operating Procedures, and design resilient systems that actively protect their engineers. By Sean Klein
AI 资讯
You Don't Need Kubernetes to Monitor 20 Linux VMs
If you've ever tried to set up Prometheus by following the official getting-started path, you're likely to find a path that does not follow your infrastructure model. Out of the gate, page one mentions kube-prometheus-stack. Page two wants you to install a Helm chart, and page three assumes you already have a cluster running. The documentation for monitoring plain Linux servers is in there somewhere, but you have to dig for it. When you do find it, the tone suggests you are doing something slightly old-fashioned. If that sounds like your setup, the tooling is making this harder than it actually is. Monitoring a fleet of Linux VMs is fairly simple and has been for years. It is just obscured behind documentation that would prefer to sell you something bigger. Modern infrastructure tooling has quietly decided everyone runs Kubernetes. If you don't, the assumption is that you eventually will. Meanwhile, most real-world infrastructure still runs on VMs. TL;DR: Modern observability documentation often assumes you're running Kubernetes. Most small teams aren't. If you're managing a fleet of Linux VMs, node_exporter plus Prometheus gives you everything you need for infrastructure monitoring with a single lightweight agent and a straightforward deployment model. No cluster required. VMs are often the answer For most small businesses, running VMs instead of Kubernetes does not mean you failed to evolve. Most workloads under a certain scale perform better on VMs: One process per box, predictable resource limits, and the ability to ssh in and look at what's happening, which makes it easier to keep track of the infrastructure as a whole. They're cheaper, both financially and in the mental overhead of running them. Backups and snapshots are straightforward in a way stateful Kubernetes still isn't. There's no control plane that itself needs monitoring and upgrades and care. Kubernetes solves problems that mostly pertain to companies with dozens of engineers and hundreds of service
AI 资讯
Too cheap to be good? Think again.
I replaced aaPanel/OpenLiteSpeed with Caddy and shell scripts and turned the process into a benchmark. Two phases (architecture then code), one external code review. The winning model? Not the one you'd expect.
AI 资讯
Deploying a Multi-Module Spring Boot App to Render with PostgreSQL, Redis, Docker, and Flyway
Deploying a Spring Boot backend should be simple in theory. Build the JAR, set the environment variables, connect the database, and ship it. In practice, my deployment exposed several assumptions that worked locally but failed immediately in the cloud. I recently deployed a modular Spring Boot application to Render using Docker, Render Blueprint, PostgreSQL, Redis, Flyway migrations, Spring profiles, Hibernate/JPA, and environment variables. The application worked locally with MySQL and Redis, but deployment exposed several production-specific issues that were easy to miss in local development. This article documents the problems, why they happened, and how I fixed them properly. Who This Article Is For This article is useful if you are deploying a Spring Boot application to Render and your local setup uses MySQL, Redis, Flyway, Docker, or a multi-module Maven structure. It is especially relevant if you are moving from a local MySQL setup to PostgreSQL in the cloud. The Stack The backend was a Java 17 Spring Boot application with multiple Maven modules: alagbafo/ ├── api-contracts ├── core ├── users ├── orders ├── payments ├── wallet ├── notifications ├── admin ├── subscriptions └── app The app module was the actual Spring Boot entry point. Locally, the project used MySQL and Redis: spring.datasource.url = jdbc:mysql://localhost:3306/alagbafo spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.data.redis.host = localhost spring.data.redis.port = 6379 For Render, the target setup was: Spring Boot app PostgreSQL database Redis-compatible Key Value store Docker deployment Flyway migrations Render Blueprint was the best fit because it allowed the infrastructure to be described in a render.yaml file. Step 1: Dockerfile for a Multi-Module Spring Boot App Because the project was a multi-module Maven application, the Dockerfile had to copy all module pom.xml files before copying the source code. This improves Docker layer caching because dependencies can b
AI 资讯
Why IT Training Matters More Than Ever in Nepal
A look at what's actually changing in Nepal's job market, what it means for students and working professionals, and what separates training that gets you hired from training that just gives you something to print on a resume. Nepal is at an interesting crossroads right now. On one side, the country still carries the weight of a job market that hasn't kept up with its graduates. Every year, more than 500,000 young people enter the workforce. The economy, for all its resilience, simply does not generate enough traditional jobs to absorb that number. The result is familiar to most Nepali families: children who studied hard, passed their exams, collected their certificates, and then spent months, sometimes years, waiting for something to happen. On the other side, something genuinely different is building. Nepal's IT exports crossed $1 billion in 2025, according to NASIT's estimates. Software and BPO exports grew over 20% in the first seven months of fiscal year 2024/25 alone. The government's 16th development plan has set a target of 250,000 new IT jobs and a 5% GDP contribution from the sector by 2029. International companies, from Indian IT majors to US-based outsourcing firms, are paying attention to Nepal in ways they weren't a decade ago. These two realities exist at the same time, in the same country, often in the same family. A brother driving a taxi while his younger sister lands a remote software development contract earning more than their father ever did in a government job. The difference between those two outcomes, more often than not, comes down to whether someone made the decision to learn something the market actually needs, and found a way to learn it properly. That's what this piece is about. The Skills Gap Problem Nobody Talks About Enough Nepal's IT sector is growing, but that growth comes with a problem attached: a persistent, widening mismatch between what employers need and what most fresh graduates can actually do on day one. Companies like Deer