今日已更新 166 条资讯 | 累计 20138 条内容
关于我们

标签:#DevOps

找到 357 篇相关文章

AI 资讯

Why API Breaking Changes Still Reach Production Even With CI/CD

Why API Breaking Changes Still Reach Production Even With CI/CD A few years ago I watched a "tiny" API change take down checkout for about forty minutes. The change was a one-liner. The pull request had two approvals. CI was green across the board. And it still broke production, because the thing that actually mattered was never tested. If you run microservices at any real scale, you have lived some version of this. Let's talk about why it keeps happening even with a mature pipeline, and what the teams who don't keep getting paged do differently. The Problem Here's the change that caused the outage. A payments service had a response that looked like this: { "status" : "ok" , "transaction_id" : "txn_8842" , "amount_cents" : 4200 } Someone renamed amount_cents to amount and switched it to a decimal, because "cents is confusing." Cleaner field, better docs. The producing service's tests were updated to match, everything passed, it shipped. The problem: three downstream services still read amount_cents . One of them was the order service, which now received undefined , multiplied it by a quantity, and wrote NaN into the database. The failures didn't even surface in the payments service. They surfaced two hops away, in a service the original author had never opened. This is the core issue. A breaking change is not defined by the service that makes it. It's defined by the consumers who depend on it. And the producer's CI pipeline has no idea those consumers exist. Why Existing Approaches Fail The natural reaction is "we need more tests." But look at what each layer actually checks. Unit tests verify the code does what the author intended. The author intended to rename the field. The unit tests were updated to expect amount . They passed because they were testing the new, broken behavior. Green unit tests told us nothing. Integration tests verify the service works with its own dependencies — its database, its cache, the APIs it calls. They almost never spin up the services

2026-06-25 原文 →
AI 资讯

AI Gateway vs API Gateway: They Solve Different Problems (We Confused Them for Six Months)

TL;DR: An API gateway manages HTTP traffic between services — auth, routing, rate limiting, load balancing for REST and gRPC. An AI gateway manages LLM workloads — token-based rate limiting, model routing, cost attribution, semantic caching, guardrails. Use an API gateway for your microservices. Use an AI gateway for your LLM traffic. Most production teams eventually need both, sitting at different layers. This post walks through exactly where each one fits. When we started adding LLM features to our platform, we already had Kong running for our microservices. The instinct was natural: route the LLM traffic through Kong too. Same auth, same rate limiting, same observability stack. One gateway to rule them all. It worked — for about six months, and only in the sense that requests got through. What it didn't give us was anything useful for actually managing AI workloads. We had no idea what each team was spending on tokens. We had no way to set a budget cap that would fire before the bill arrived. Our rate limits were based on requests per minute, which meant a single request with a 50k token prompt counted the same as one with a 200 token prompt. And when OpenAI had a partial outage, Kong had no concept of "try Anthropic instead" — we just served errors. None of that is a criticism of Kong. It's doing exactly what it was designed to do. The problem was us expecting an API gateway to handle a fundamentally different category of infrastructure problem. Here's the precise distinction, and why it matters architecturally. What an API gateway actually does An API gateway is a reverse proxy that sits between client applications and backend services. It handles the cross-cutting concerns of service-to-service HTTP communication: authentication, authorization, rate limiting, load balancing, SSL termination, request transformation, and routing based on URL paths or headers. A typical request flow through an API gateway: Client sends a request to the gateway endpoint Gateway ve

2026-06-24 原文 →
AI 资讯

I built a local-only credential vault because every dev team I worked with stored PATs in Notepad

The Problem I Kept Seeing Over the past year working across multiple client teams on DevOps and pipeline work, I kept noticing the same thing. Developers storing GitHub PATs in Notepad. QA engineers keeping API keys in a text file on the desktop. DevOps folks with database passwords in a sticky note app. During screen shares — sprint reviews, debugging sessions, pair programming, recorded demos — those credentials were just sitting there. Visible to everyone in the call. Nobody said anything. It just kept happening. Why Existing Tools Didn't Fit I looked for something simple that solved this. Here's what I found and why none of it quite worked: Password managers (1Password, Bitwarden) Good tools. But they're built around cloud sync, browser extensions, and team sharing. For an individual developer who just wants somewhere safe to keep a PAT — overkill. Also: corporate IT policies often block installation of cloud-synced password managers on work machines. Secret managers (HashiCorp Vault, AWS Secrets Manager) These are infrastructure tools, not personal workflow tools. Setting up Vault for an individual developer's PAT collection is like using a forklift to move a chair. OS keystores (Windows Credential Manager, macOS Keychain) Actually decent for storage. But no UI built for this workflow, no copy-to-clipboard, and they don't solve the screen-exposure problem at all. The gap: Something simple, local, and designed around the moment of use — not just storage. So I Built Tokenly Tokenly is a local-only desktop credential vault. The core design principle is simple: Credential values are never shown on screen. You copy them to clipboard. That's the only way to use them. The clipboard auto-clears after 30 seconds. If you need to visually verify a value — press and hold a button. Release it, the value hides immediately. Not a toggle — a hold. Toggles get forgotten. Holds don't. Technical Decisions Worth Explaining Why Tauri over Electron Tauri uses the operating system's

2026-06-24 原文 →
AI 资讯

Day 33: Understanding ClickHouse® Query Execution Plans

Introduction When a query runs in ClickHouse®, the database does much more than simply read data and return results. Before execution begins, ClickHouse® parses the SQL statement, analyzes it, applies optimizations, and builds an execution plan that determines the most efficient way to process the query. Understanding query execution plans is one of the most valuable skills for anyone working with ClickHouse®. They provide visibility into how queries are executed, helping you identify bottlenecks, validate optimization efforts, and troubleshoot performance issues. In this article, we'll explore how ClickHouse® generates execution plans, the different EXPLAIN modes, and how to interpret them for better query optimization. Why Query Execution Plans Matter A SQL query defines what data you want, but it doesn't explain how the database retrieves it. Consider the following query: SELECT country , count () FROM events GROUP BY country ; Although the query looks simple, ClickHouse® must determine: Which data parts to read Whether primary indexes can reduce the scan If data skipping indexes can be used How aggregation should be performed Whether parallel execution is possible How intermediate results should be merged A query execution plan provides answers to these questions, making it an essential tool for performance tuning. The ClickHouse Query Lifecycle Every query passes through several stages before producing results. The lifecycle typically looks like this: SQL Query │ ▼ Parser │ ▼ Analyzer │ ▼ Optimizer │ ▼ Query Plan │ ▼ Execution Pipeline │ ▼ Results Each stage plays an important role: Parser validates SQL syntax. Analyzer resolves tables, columns, and expressions. Optimizer applies query optimizations. Query Plan determines the logical execution steps. Pipeline distributes work across multiple threads. Execution processes the data and returns the results. Understanding this workflow makes execution plans much easier to interpret. Introducing the EXPLAIN Statement

2026-06-24 原文 →
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

2026-06-24 原文 →
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

2026-06-24 原文 →
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

2026-06-24 原文 →
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 - --

2026-06-24 原文 →
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

2026-06-24 原文 →
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"

2026-06-24 原文 →
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" - " --

2026-06-24 原文 →
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

2026-06-24 原文 →
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 :

2026-06-24 原文 →
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

2026-06-24 原文 →
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 :

2026-06-24 原文 →
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

2026-06-24 原文 →
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

2026-06-23 原文 →
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

2026-06-23 原文 →
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

2026-06-23 原文 →