AI 资讯
Deploying ImgProxy – Process, Resize, Convert Images on the Fly
ImgProxy is an open-source image-processing server — resize, convert, and transform images on the fly via URL parameters, ideal as a caching layer in front of a CDN or web app. This guide builds ImgProxy from source on Ubuntu, runs it as a systemd service behind Nginx with TLS, walks through its URL processing options, and secures it with signed URLs. Prerequisites: an Ubuntu server, a domain A record (e.g. imgproxy.example.com ), non-root sudo user. Install ImgProxy ImgProxy uses libvips for image processing; this builds it from source with Go. $ sudo add-apt-repository ppa:dhor/myway $ sudo apt update $ sudo apt install libvips-dev -y $ sudo snap install --classic --channel = latest/stable go $ git clone https://github.com/imgproxy/imgproxy.git $ cd imgproxy $ sudo CGO_LDFLAGS_ALLOW = "-s|-w" go build -o /usr/local/bin/imgproxy Create the environment config: $ sudo touch /usr/local/bin/imgproxy.env $ sudo nano /usr/local/bin/imgproxy.env IMGPROXY_BIND = :8080 IMGPROXY_NETWORK = tcp IMGPROXY_READ_TIMEOUT = 10 IMGPROXY_WRITE_TIMEOUT = 10 IMGPROXY_WORKERS = 2 IMGPROXY_REQUESTS_QUEUE_SIZE = 0 IMGPROXY_QUALITY = 100 IMGPROXY_PREFERRED_FORMATS = webp,jpeg,png,gif,avif IMGPROXY_LOG_FORMAT = "pretty" IMGPROXY_LOG_LEVEL = "INFO" IMGPROXY_WATERMARK_URL = https://example.com/watermark.png IMGPROXY_WATERMARK_OPACITY = 1 Key settings: IMGPROXY_WORKERS should be ~2× your vCPU count; IMGPROXY_REQUESTS_QUEUE_SIZE=0 means unlimited queueing; IMGPROXY_WATERMARK_URL points at whatever image you want overlaid when watermarking is enabled. Point ImgProxy at the config and test: $ export IMGPROXY_ENV_LOCAL_FILE_PATH = /usr/local/bin/imgproxy.env $ cd $ imgproxy WARNING [2024-05-28T00:40:42Z] No keys defined, so signature checking is disabled WARNING [2024-05-28T00:40:42Z] No salts defined, so signature checking is disabled INFO [2024-05-28T00:40:42Z] Starting server at :8080 Stop it with Ctrl+C once verified, then set it up as a service. Run ImgProxy as a systemd Service $ sudo useradd
AI 资讯
Deploying code-server for VS Code on Ubuntu 24.04
code-server is the open-source project that runs full VS Code including extensions, integrated terminal, Git, IntelliSense — on a remote server, accessible from any browser. This guide deploys it on Ubuntu 24.04 with Docker Compose, fronted by Traefik for automatic HTTPS. Prerequisites: an Ubuntu 24.04 server (1GB RAM / 2 vCPU minimum), a domain A record (e.g. code.example.com ), Docker and Docker Compose installed. Set Up the Project $ mkdir -p ~/vscode-server/ { project,config,local,letsencrypt } $ cd ~/vscode-server project — your editable workspace config — code-server settings/extensions local — user-specific data letsencrypt — Traefik's ACME certificate storage Find your UID/GID and add yourself to the docker group: $ id $USER $ sudo usermod -aG docker $USER Write the Compose File $ nano docker-compose.yml services : code-server : image : codercom/code-server:latest container_name : code-server user : " UID:GID" # Replace with your user's UID and GID environment : - PASSWORD=SECURE_PASSWORD # Replace with a strong password - DOCKER_USER=LINUXUSER # Replace with your username volumes : - ./project:/home/coder/project - ./config:/home/coder/.config - ./local:/home/coder/.local networks : - internal restart : unless-stopped labels : - " traefik.enable=true" - " traefik.http.routers.code-server.rule=Host(`CODE.EXAMPLE.COM`)" # Replace with your domain name - " traefik.http.routers.code-server.entrypoints=websecure" - " traefik.http.routers.code-server.tls.certresolver=myresolver" - " traefik.http.services.code-server.loadbalancer.server.port=8080" traefik : image : traefik:latest container_name : traefik 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" - " --providers.docker.network=internal" - " --entrypoints.web.address=:80" - " --entrypoints.websecure.address=:443" - " --entrypoints.web.http.redirections.entr
AI 资讯
Deploying Metabase on Kubernetes
Metabase is an open-source BI tool for building charts and dashboards over MySQL, PostgreSQL, MongoDB, Redshift, and more. This guide deploys Metabase on Kubernetes, loads the Sakila sample dataset into MySQL, builds a dashboard, and secures it behind Nginx Ingress with cert-manager TLS. Prerequisites: a Kubernetes cluster with kubectl / helm configured, a Linux workstation, a reachable MySQL server, and a domain name. Load the Sakila Sample Database Sakila models a DVD rental store — films, actors, inventory, rentals. $ sudo apt install zip -y $ wget https://downloads.mysql.com/docs/sakila-db.zip $ unzip sakila-db.zip Connect to your MySQL server (replace host/port/user): $ mysql -h <HOST_ENDPOINT> -P <DATABASE_PORT> -u <ADMIN_USER> -p mysql > CREATE DATABASE sakila ; mysql > SOURCE sakila - db / sakila - schema . sql ; mysql > SOURCE sakila - db / sakila - data . sql ; Deploy Metabase $ nano metabase.yaml apiVersion : apps/v1 kind : Deployment metadata : name : metabase spec : selector : matchLabels : app : metabase replicas : 1 template : metadata : labels : app : metabase spec : containers : - name : metabase image : metabase/metabase:latest ports : - containerPort : 3000 protocol : TCP --- apiVersion : v1 kind : Service metadata : name : metabase-svc spec : type : LoadBalancer selector : app : metabase ports : - name : http port : 8080 targetPort : 3000 Your cloud provider may need a provider-specific LoadBalancer annotation here (e.g. to set the listener protocol) — check its Kubernetes docs if the default doesn't work. $ kubectl apply -f metabase.yaml $ kubectl get deployments $ kubectl get services Wait for metabase-svc to get an EXTERNAL-IP (can take a few minutes), then visit http://<external-ip>:8080 to confirm the Metabase welcome page loads. Connect Metabase to the Database Let's get started → pick language. Enter your name, email, company, and a password. Select your use case. Database engine: MySQL . Set a display name, then host/port/database/user/pa
AI 资讯
Installing Nginx UI – An Open-Source WebUI for Nginx
Nginx UI is an open-source web GUI for managing Nginx, single-node or clustered, with real-time stats, automatic Let's Encrypt TLS, performance monitoring, and even LLM-assisted config editing. This guide installs it on Ubuntu 24.04, puts it behind a reverse proxy with TLS, sets up ACME certificate management, and creates a virtual host through the dashboard. Prerequisites: an Ubuntu 24.04 server, non-root sudo user, a domain A record (e.g. nginx-ui.example.com ), Docker installed if you choose that install path. $ sudo apt update $ sudo apt install nginx -y Pick one of the two install methods below. Option A: Install via Script Runs Nginx UI as a system service, managing the host's Nginx directly. $ curl -O https://cloud.nginxui.com/install.sh $ sudo bash install.sh install $ nginx-ui --version $ sudo systemctl start nginx-ui $ sudo systemctl status nginx-ui Option B: Install via Docker Runs as a container — you won't be able to edit the host's Nginx configs directly through it. $ mkdir -p ~/nginx-ui-docker $ cd ~/nginx-ui-docker $ sudo mkdir -p /opt/nginx-ui/nginx $ sudo mkdir -p /opt/nginx-ui/config $ sudo mkdir -p /opt/nginx-ui/www $ nano docker-compose.yml version : ' 3.8' services : nginx-ui : image : uozi/nginx-ui:latest container_name : nginx-ui restart : always environment : - TZ=UTC volumes : - /opt/nginx-ui/nginx:/etc/nginx - /opt/nginx-ui/config:/etc/nginx-ui - /opt/nginx-ui/www:/var/www ports : - " 127.0.0.1:9000:80" networks : - nginx-ui-net networks : nginx-ui-net : driver : bridge $ sudo docker compose up -d $ sudo docker compose ps $ curl -X GET http://localhost:9000 Configure the Reverse Proxy Nginx UI listens on localhost:9000 . Put it behind a public vhost with WebSocket support (needed for live stats/terminal): $ cd /etc/nginx/sites-available $ sudo nano nginx-ui.conf map $http_upgrade $connection_upgrade { default upgrade ; '' close ; } server { listen 80 ; listen [::]:80 ; server_name nginx-ui.example.com ; location / { proxy_set_header Host $
AI 资讯
Testing CAST AI on GKE: A Hands-On Kubernetes Workload Optimization Lab
Kubernetes makes it easy to define CPU and memory requests for our applications. But there is a problem: How do we know whether those resource requests are actually correct? If an application requests: yaml resources: requests: cpu: "1000m" memory: "1Gi" but normally consumes only a few millicores of CPU and a few megabytes of memory, we may be reserving significantly more cluster capacity than the workload actually needs. I wanted to understand how Kubernetes cost optimization platforms detect this situation, so I built a small hands-on lab using: Google Kubernetes Engine (GKE) CAST AI Kubernetes Docker FastAPI Google Artifact Registry The goal wasn't simply to install CAST AI. I wanted to observe the complete process: Deploy workload ↓ Observe resource usage ↓ Compare requests vs usage ↓ Identify over-provisioning ↓ Generate recommendation ↓ Apply rightsizing ↓ Verify from Kubernetes Architecture The lab architecture was intentionally simple. FastAPI Coffee API | v Docker Image | v Google Artifact Registry | v GKE Cluster | v Kubernetes Deployment | +----------------+ | | v v Pod #1 Pod #2 | | +-------+--------+ | v ClusterIP Service + | v CAST AI | +-------+-------+ | | v v Cost Monitoring Workload Optimization 1. Building a Small Test Application I created a very small FastAPI application for the experiment. from fastapi import FastAPI import socket import os import time app = FastAPI() @app.get("/") def home(): return { "message": "Coffee Shop API", "hostname": socket.gethostname(), "pod": os.getenv("HOSTNAME"), "time": time.time() } @app.get("/coffee") def coffee(): return { "coffee": "Cappuccino", "price": 120 } The hostname in the response was useful later because I could see which Kubernetes Pod handled each request. 2. Containerizing the API The application was packaged using Docker. FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . EXPOSE 8000 CMD ["uvicorn", "app:app", "--host", "0
AI 资讯
What Payments Infrastructure Taught Me About Building Systems That Don't Break
Idempotency, vendor failure, monitoring that catches the invisible outages, and the tradeoffs nobody warns you about, lessons from scaling payments infrastructure. Most software fails quietly. A page renders slowly, a recommendation is a little off, a report is stale by an hour. Users shrug and move on. Payments doesn't work like that. When payments break, someone's money is in a place neither of you can account for, and the clock starts ticking on their patience. There's no graceful degradation. Either the money moved, or it didn't, and someone needs to know which. I've spent a good chunk of my career building and scaling payments infrastructure, and it has quietly rewired how I think about engineering in general. Here's what stuck. 📋 The short version # Lesson One-line summary 1 Idempotency You will receive the same request twice. Design for it. 2 Vendor failure Gateways are vendors. Ask "when," not "if." 3 Monitoring Never learn about an outage from a customer. 4 The unglamorous stuff Ledgers, reconciliation, state machines, refunds. 5 Tradeoffs Every lesson above fights at least one other. 1. 🔁 Idempotency isn't a feature. It's a foundation. The first hard lesson: you will receive the same request twice. Not "might." Will. A client times out waiting for your response and retries. A user double-taps a button on a bad connection. A queue consumer crashes after processing but before acknowledging. A gateway sends the same webhook four times because it never got a 200 back. None of these are exotic failure modes, they're Tuesday. If your system treats every incoming call as a new instruction, every one of those scenarios becomes a double charge. And a double charge isn't a bug you fix quietly in the next release. It's a support ticket, a refund, a reconciliation entry, and a customer who now checks their statement every time they use you. The fix is conceptually simple and operationally demanding: every operation that moves money must be uniquely identifiable and sa
AI 资讯
We added mobile approvals to our CLI AI tool -- approve Claude's destructive commands from your phone
Quick share of a feature we built into Telechat (self-hosted Claude AI bot) that's been surprisingly useful for devops workflows: Desktop Bridge with mobile approvals . The problem You're running Claude Code (or any Claude-powered agent) on your workstation. It's refactoring a module, running tests, deploying to staging. You step away for coffee, a meeting, or just to stretch. Claude hits a tool call that needs human approval: rm -rf build/ (wants to clean the build directory) git push --force (rebase gone wrong) kubectl delete pod (scaling decision) Without you at the keyboard, it just... waits. For however long you're gone. The solution Telechat's Desktop Bridge connects your Claude Code session to your phone via Telegram, WhatsApp, or Slack. When Claude needs approval: You get a push notification with exactly what Claude wants to execute You see the full command and context You tap Approve or Deny Claude continues (or backs off) All from your phone. No VPN, no SSH, no laptop. Why this matters for devops Unattended CI/CD with a human gate. Run Claude as part of your pipeline for code review, test generation, or deployment prep. Gate the destructive steps on mobile approval instead of blocking the pipeline until someone checks Slack. Overnight tasks. Kick off a large refactoring or migration analysis before bed. If Claude needs a decision at 2 AM, you'll see it in the morning and approve from your phone. It doesn't lose context while waiting. Pair programming while mobile. Reviewing Claude's work from your phone between meetings. Approve the good stuff, deny the risky stuff, add context via chat. How it works Telechat runs on your workstation alongside Claude Code. It acts as a bridge between Claude's approval prompts and your messaging app. When Claude's tool-use loop hits a human-approval checkpoint, Telechat intercepts it, formats the request, and sends it to your Telegram/WhatsApp/Slack. Your response flows back and unblocks the agent. No cloud relay — the brid
AI 资讯
CISA KEV catalog: a working sysadmin's guide to actually using it
Most enterprise teams know the CISA Known Exploited Vulnerabilities catalog the same way they know the weather: a headline scrolls past ("CISA adds three vulnerabilities to KEV catalog"), someone forwards it, and everyone nods. That is a waste of the single most operationally useful list in vulnerability management. The KEV is small, machine-readable, updated near-daily, and every entry on it has one property your scanner output cannot give you: a real attacker has already used it against a real network. This is a guide to the catalog itself: what it promises, what it doesn't, how the feeds are structured, how to map entries to your own estate without fooling yourself, and how to combine it with EPSS and vendor advisories into a defensible patch-ordering rule. Everything here is verified against the live feed and CISA's own pages as of late July 2026. What the KEV is, and what it is not CISA describes the KEV as the authoritative source of vulnerabilities that have been exploited in the wild . Entry is gated by three criteria , all of which must hold: The vulnerability has an assigned CVE ID. There is reliable evidence of active exploitation in the wild. There is a clear remediation action, such as a vendor-provided update. Read those criteria as exclusions and the catalog's real shape appears. No CVE assigned yet? Not in the KEV, even if exploitation is rampant. Exploitation reported but CISA's evidence bar not met? Not in the KEV. Actively exploited but no fix or mitigation exists? Not in the KEV. The catalog is a curated floor, not a census. As of the 2026.07.29 release the feed contains 1,656 entries, against an ecosystem publishing tens of thousands of CVEs per year. Absence from the KEV is not evidence of safety; presence is close to proof of danger. That asymmetry is the whole point, and it is why the correct reading of the list is "everything on here is urgent" rather than "everything urgent is on here." The distribution is also worth knowing before you buil
AI 资讯
Stopping Runaway AI Loops: Implementing Enterprise FinOps and Observability with PolicyAware
Autonomous agents don't just fail loudly—they fail expensively. A single misconfigured retry loop between an agent and an LLM can generate thousands of redundant tool calls and API requests before anyone notices, turning a minor logic bug into a five-figure cloud bill. PolicyAware is built to be the operational safety net that catches this class of failure before it reaches your finance team's dashboard. 1. The Recursive Agent Crisis Every SRE and platform engineer who has run agentic workloads in production has a version of this story. An agent is wired to call an LLM, interpret the response, and take an action—often invoking another tool, which produces output that gets fed straight back into the same LLM. Under normal conditions this loop terminates in a few steps. Under a bad prompt, a malformed tool response, or a subtle logic error, it doesn't. The agent gets stuck reasoning in circles: it calls a tool, receives an ambiguous or malformed result, decides the task is incomplete, and calls the LLM again to "retry." Each retry consumes tokens, each tool call hits a downstream API, and there is no natural circuit breaker unless one has been explicitly engineered. Within minutes, a single stuck session can produce: Thousands of duplicate or contradictory API calls to internal and third-party services. Sustained LLM token consumption that dwarfs normal daily usage. Cascading load on downstream systems that were never designed for machine-speed request volume. By the time monitoring dashboards catch the anomaly—if they catch it at all—the damage is already done: a runaway bill, a rate-limited API partner, or a compromised production database from thousands of unchecked write attempts. Traditional APM tools tell you a service is under load; they don't tell you an autonomous agent is the one generating that load, or why. This is why the recursive agent crisis is fundamentally a governance problem, not just a monitoring problem. Rate limits and cost alerts fire after the
AI 资讯
I checked every MCP server in the official registry. About 1 in 10 is broken.
There is a number going around that roughly half of all remote MCP servers are dead. I had repeated it myself, in the README of a tool I published. I could not find where it came from, so I measured it. The answer is that about one in ten is actually broken. The "half" figure appears to come from counting servers that require an API key as if they were down. Here is the method and the full breakdown. What I measured On 29 July 2026 I pulled every entry from the official MCP registry — 1,200 servers. Of those, 297 had status: active and advertised a remote endpoint URL (the rest are stdio/local packages with nothing to probe over the network). Each got one anonymous JSON-RPC initialize over streamable HTTP, with a 10 second timeout: { "jsonrpc" : "2.0" , "id" : 1 , "method" : "initialize" , "params" : { "protocolVersion" : "2025-06-18" , "capabilities" : {}, "clientInfo" : { "name" : "mcp-uptime" , "version" : "0.1.0" } } } Then I classified the response: a valid result containing protocolVersion or serverInfo is up, 401/403 is auth-gated, and everything else got bucketed by its actual failure. Results (n = 297) Result Count Share Completed an MCP handshake 133 44.8% Auth-gated (401/403) 134 45.1% DNS failure 8 2.7% Server error (5xx) 6 2.0% Not found (404/410) 5 1.7% Redirect (307/308) 4 1.3% Timeout 2 0.7% Non-MCP response 2 0.7% Other (400, 405, connection) 3 1.0% Reachable: 267 (89.9%). Genuinely broken: 30 (10.1%). Where "half are dead" comes from Look at the first two rows. 55.2% of these endpoints will not complete an anonymous handshake — and that is suspiciously close to the number people quote. But 134 of those 164 are returning a clean 401 or 403. They are running. They are answering. They want an API key, which is a completely reasonable thing for a hosted service to want. Counting those as dead inflates the failure rate by roughly five times. This matters beyond pedantry: if you believe half the ecosystem is rubble, you build defensively against the wron
AI 资讯
Your Agent's Memory Is a Markdown File. Let's Audit It.
Quick check: does your agent stack have a memory.md in it somewhere? An AGENTS.md ? A notes file the agent appends to when something seems worth keeping? Thought so. Mine did too. It's the pattern everyone converges on, it takes twenty minutes to build, and it genuinely works — right up until the day it hands a customer a fact that stopped being true in March. This post does three things: shows you exactly why the pattern rots (with a real-shaped sample file we'll dissect), gives you a small script to audit your own file tonight, and walks through the architecture change that actually fixes it. No vendor required for any of it. The pattern we all built Strip away the framework and every self-managed memory loop looks like this: MEMORY = Path ( " memory.md " ) def run_task ( task : str ) -> str : context = MEMORY . read_text () # 1. dump everything in result = llm ( SYSTEM + context + task ) # 2. do the actual job note = llm ( # 3. agent grades its own homework " What from this interaction is worth remembering? " " Reply with one line, or NONE. \n\n " + result ) if note . strip () != " NONE " : with MEMORY . open ( " a " ) as f : # 4. append forever f . write ( f " - { note . strip () } \n " ) return result Be fair to it first: this is human-readable, versionable, greppable, zero-infrastructure. For one agent, one job, small working set — it's honestly hard to beat. Now look at what it doesn't do. Step 4 is the entire lifecycle. Nothing in this loop ever updates, merges, expires, or questions a line once written. The file has exactly one behavior: it grows. Dissecting a six-month-old memory file Here's a condensed, realistic slice of what that loop produces by month six. Read it the way retrieval reads it — every line equally true: - Customer Acme runs their workload in us-east1 - Acme prefers Slack over email for escalations - Acme's staging env uses the legacy auth flow - Acme contact is Priya (prefers email) - The feature flag `beta_router` must stay ON for Acme -
AI 资讯
DSCI series / Rakulang CI, part2. Cro Application
In this episode I talk about developing web application based on well known cro framework and specifically how to create CI pipeline using DSCI tool. Here is example of very simple cro application (taken from cro web site): use Cro::HTTP:: Router ; use Cro::HTTP:: Server ; my $application = route { get -> { content ' text/html ', ' Hello Cro! '; } } my Cro:: Service $service = Cro::HTTP:: Server . new : : host < localhost > , : port < 10000 > , : $application ; $service . start ; react whenever signal ( SIGINT ) { $service . stop ; exit ; } First of all let's create jobs file .dsci/jobs.yaml that would contain list of jobs, in our case this is just a single job: jobs : - id : ci path : . In this case we would have just a single job that: installs apps dependencies runs web application in background runs some end to end tests using http client .dsci/job.raku run_task " install "; run_task " end-to-end "; .dsci/tasks/install/task.bash set -e cd ../ ls -l zef install . --deps-only zef install . echo "done" nohup cro run 1>app.log 2>&1 & </dev/null The first task just installs application dependencies and runs web application in background, now we can create some end to end test. For simplicity I am going to use curl http client here, but feel free choose any languages you like, for example Raku's HTTP::Tiny client, DSCI is super flexible allowing to write tasks on different languages mixing then effectively. .dsci/tasks/end-to-end/task.bash I could have made this simple one line Bash task a part of initial install task, but for claritrty and demonstration of modularity I keep as a separate one. In the future more tests may come (rathe then this trivial one) and it reasonable separate installation and testing logic. set -e # the test should fail if HTTP response is not # successful curl 127.0.0.1 127.0.0.1:10000 -f -L Ok, let's try this out. And the very first run results in ... error: 08:47:39 :: ===> Building: Digest::SHA1::Native:ver<1.0.1>:auth<zef:bduggan> 08:47:39
AI 资讯
Build a Dependency Vulnerability Scanner with Python
Build a Dependency Vulnerability Scanner with Python tags: python, security, devops, tools tags: python, security, devops, tools Build a Dependency Vulnerability Scanner with Python Your requirements.txt looks clean, but one of those dependencies might be a ticking time bomb waiting to expose your users to a data breach. You don’t need to wait for a security audit to find out—you can build your own lightweight vulnerability scanner in Python today and integrate it directly into your workflow. Security isn’t just about writing secure code; it’s about knowing what’s running in your environment. With thousands of Python packages available, the odds that you’re using a library with a known CVE (Common Vulnerabilities and Exposures) are high. Instead of relying solely on third-party tools like pip-audit or safety (which are excellent, but sometimes opaque), building your own scanner gives you full control over how vulnerabilities are detected, reported, and acted upon. Let’s build a practical, working dependency vulnerability scanner from scratch. Why Build Your Own Scanner? Existing tools like pip-audit [13], safety [10], and PySentry [4] are powerful, but they come with limitations: They may not support your specific output format (e.g., custom JSON for CI). They might not integrate cleanly with your private PyPI registry. You can’t easily tweak the logic to match your team’s risk tolerance. Building your own scanner lets you: Query the NVD (National Vulnerability Database) API directly. Parse requirements.txt , pyproject.toml , or poetry.lock files flexibly. Generate reports in any format you need (Markdown, JSON, SARIF). Fail your CI pipeline automatically when critical CVEs are found. Plus, it’s a great learning exercise in cybersecurity, API integration, and Python parsing. Step 1: Set Up Your Environment Before writing code, prepare a clean virtual environment to avoid false positives from global packages: python3 -m venv scanner-env source scanner-env/bin/activat
AI 资讯
File Compression in Linux Explained Simply (tar, gzip, zip & unzip)
Working with files in Linux isn't just about creating and editing them. Sometimes you need to: Archive multiple files into one Compress files to save disk space Share files with others Create backups Linux provides several tools for this, each with a different purpose. Let's simplify them. What is File Compression? File compression reduces the size of a file. Benefits: Saves disk space Faster file transfers Easier backups Reduces bandwidth usage Example: A 100 MB log file might become a much smaller compressed file, depending on its contents. Archive vs Compression Many beginners think they're the same. They are not. Archive Combines multiple files into a single file. Example: photos/ docs/ notes.txt ↓ backup.tar Compression Reduces the size of a file. Example: backup.tar ↓ backup.tar.gz 👉 tar archives files. gzip compresses them. 1. Create an Archive with tar tar -cvf backup.tar Documents/ #Create an archive tar -tvf backup.tar #View archive contents tar -xvf backup.tar #Extract an archive Options: c → Create v → Verbose (show progress) f → File name x → Extract Best for: Backups Bundling multiple files Moving folders 2. Compress with gzip Compress a file: gzip file.txt # Creates file.txt.gz # Result file.txt.gz gunzip file.txt.gz # decompress gzip -k file.txt # Keep original file Best for: Log files Large text files Saving disk space 3. Archive and Compress Together Most common command: # Create compressed archive tar -czvf backup.tar.gz Documents/ # Extract tar -xzvf backup.tar.gz Options: z → Use gzip compression 👉 This is one of the most common backup commands in Linux. 4. Working with ZIP Files # Create ZIP zip -r project.zip project/ # Extract unzip project.zip # List contents unzip -l project.zip Best for: Sharing files with Windows users Cross-platform compatibility 5. Compare the Tools Tool Purpose Best For tar Archive files Backups gzip Compress files Saving space tar + gzip Archive and compress Linux backups zip Archive and compress Sharing files across
AI 资讯
Working with Let's Encrypt's Short-Lived tlsserver and shortlived Profile Certificates
Let's Encrypt issues TLS certificates with a 90-day validity period by default. However, as the industry is gradually shortening TLS certificate lifetimes—with the maximum eventually expected to fall to 47 days—Let's Encrypt already offers certificates using the tlsserver profile with a validity period of 45 days. Compared with the current default classic profile, the tlsserver profile removes deprecated attributes such as the Common Name. Because it follows the latest recommended configuration, it also produces slightly smaller certificates. The differences between the profiles are documented on the following page. If you have already automated certificate issuance and renewal, it is worth considering an early move to the tlsserver profile. Certificate Profiles - Let's Encrypt Certificates issued with the classic profile are currently valid for 90 days. However, the validity period is scheduled to be shortened to 64 days in February 2027 and then to 45 days in February 2028. Certificate renewal automation is easy to leave untouched once it is working, and many monitoring systems also use fixed day-based thresholds. Both renewal automation and monitoring therefore require careful review. Decreasing Certificate Lifetimes to 45 Days - Let's Encrypt With only about six months remaining before the validity period is reduced to 64 days, now is a good time to begin validating your systems. Let's Encrypt also provides the shortlived profile for certificates that support IP addresses. These certificates are valid for only six days. With such a short lifetime, using them without automation is no longer practical. 6-Day and IP Address Certificates - Let's Encrypt To issue certificates using any of these profiles, you need an ACME client that supports ACME profile selection. Widely used clients such as Certbot should be able to issue them without difficulty. Issuing a certificate with the new tlsserver or shortlived profile is straightforward. The harder part is keeping it ren
AI 资讯
What Actually Happens After You Send a Webhook
The first version of a webhook is always the same four lines: await fetch(customer.webhookUrl, { ...
AI 资讯
Building an On-Premise Kubernetes Cluster — Part 6: Deploying, Updating, and Scaling Your Own Application
🇧🇷 Leia a versão em português aqui In Part 5 of this series, we validated the cluster end to end by deploying Nginx. Now let's go one step further: build a custom application's Docker image, publish it, get it running in the cluster, and explore day-to-day operations — version updates, rollback, and scalability (both manual and automatic). As an example, we used a simple REST API ( myapp.war ), built with Spring Boot, purely for illustration — the process applies to any application packaged as a container image. Building the application's Docker image The first step is writing the application's Dockerfile . In this example, a lightweight base image ( alpine ) was used, with Java 11 installed to run the application: FROM alpine WORKDIR /opt/app RUN apk update && apk add vim openjdk11-jre COPY runapp.sh . CMD ash runapp.sh Building the image docker image build -t oregontecnologia/myapp-api:1.0.0 . Publishing the image Before using the image in the cluster, it needs to be available in some registry — either Docker Hub or a private registry . If you'd rather host your own on-premise registry (recommended for corporate environments or those without internet access), check out the companion article on creating a local registry server . To publish to Docker Hub: docker login username: password: docker push oregontecnologia/myapp-api:1.0.0 Deploying the application With the image published, you can check the cluster's current state before proceeding: kubectl get pods -o wide kubectl get deploy -o wide Create the Deployment directly from the command line, pointing to the published image: kubectl create deploy myapp-deploy --image = oregontecnologia/myapp-api:1.0.0 Unlike previous examples in this series (where we used YAML files with kubectl apply -f ), here the Deployment is created directly via the command line with kubectl create deploy . Both approaches are valid — YAML files are more suitable when you need to version and consistently reapply configurations. Exposing the
AI 资讯
Building an On-Premise Kubernetes Cluster — Part 5: Deploying Your First Container
🇧🇷 Leia a versão em português aqui In previous parts of this series, we built the cluster from scratch: prepared the environment (Part 1), installed containerd and Kubernetes (Part 2), initialized the control-plane (Part 3), and joined the workers (Part 4). With the cluster up and all nodes in Ready state, it's time to actually put it to work: let's deploy our first application. In this article, we'll use Nginx as an example — a classic use case for validating that the cluster is working end to end, from pod creation to service exposure. Organizing the files First, create a directory to organize this deployment's manifests: mkdir nginx cd nginx Keeping Kubernetes manifests organized in per-application directories is a good practice that makes maintenance and versioning (e.g., with Git) easier as the cluster grows. Creating the Deployment A Deployment is the Kubernetes object responsible for managing pod replicas, ensuring the desired number of instances is always running — and handling things like rolling updates and automatic recovery in case of failure. Create the file nginx-deployment.yaml with the following content: apiVersion : apps/v1 kind : Deployment metadata : name : nginx-deployment labels : app : nginx spec : replicas : 2 selector : matchLabels : app : nginx template : metadata : labels : app : nginx spec : containers : - name : nginx image : nginx:1.14.0 ports : - containerPort : 80 This manifest defines: 2 replicas of the Nginx pod ( replicas: 2 ), distributed across the available workers; A selector that ties the Deployment to the pods via the app: nginx label; The nginx:1.14.0 image, exposing container port 80 . Applying the Deployment With the file saved, apply it to the cluster: kubectl apply -f nginx-deployment.yaml kubectl will create the Deployment, and from there Kubernetes takes care of scheduling the 2 pods across the available workers. Checking the Deployment To confirm the Deployment was created and has the desired number of replicas running
AI 资讯
Building an On-Premise Kubernetes Cluster — Part 2: Installing Containerd and Kubernetes
🇧🇷 Leia a versão em português aqui In Part 1 of this series, we prepared the environment: defined the hardware, configured /etc/hosts , adjusted the firewall, and disabled SWAP on all nodes. Now that the foundation is ready, it's time to install the container runtime ( containerd ) and the Kubernetes packages themselves ( kubelet and kubeadm ). All the steps below should be run on all servers in the cluster — master and workers — unless stated otherwise. Loading kernel modules Kubernetes, through containerd, depends on two Linux kernel modules: overlay (for the layered filesystem used by containers) and br_netfilter (so that bridge network traffic passes through iptables rules). For these modules to load automatically on every boot, create the file /etc/modules-load.d/containerd.conf : overlay br_netfilter And, to load them immediately (without needing a reboot), run: $ sudo modprobe overlay $ sudo modprobe br_netfilter Adjusting kernel network parameters Create the file /etc/sysctl.d/99-kubernetes-k8s.conf with the following parameters: net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 These parameters ensure that network traffic between pods and services is correctly routed and filtered by Kubernetes. To apply the settings without restarting the server: $ sudo sysctl --system Installing containerd Containerd is the container runtime used by the cluster. In this case, we'll install it through Docker's official repository, using only the containerd.io package (without installing full Docker). 1. Download the repository's GPG key: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg 2. Create the repository file at /etc/apt/sources.list.d/docker.list : deb [ arch = amd64] https://download.docker.com/linux/debian bullseye stable 3. Update the package list and install containerd: sudo apt-get update sudo apt-get install containerd.io 4. Generate the default
开发者
Building an On-Premise Kubernetes Cluster — Part 1: Preparing the Environment
🇧🇷 Leia a versão em português aqui This is the first part of a series where I'll share, step by step, how I built my own on-premise Kubernetes cluster, without relying on any cloud provider. The goal is to document the whole process — from environment preparation to a working cluster — as a reference for anyone studying the topic or looking to replicate the same setup at home or at work. I used VPS (Virtual Private Server) and VM (Virtual Machine) for this cluster. However, it can also be set up on physical machines (Bare Metal). Bye the end of this series, it will be easier to understand cloud clusters on AWS (EKS), Google (GKE) and Azure (AKS). In this first part, we'll cover everything needed before installing any Kubernetes component: hardware requirements, basic network configuration, firewall rules, and a few mandatory operating system adjustments. Requirements The following topology was used for this cluster: 3 servers in total 1 master server (control-plane): 2 CPUs (cores) and 2 GB of RAM 2 worker servers (slaves): 1 CPU and 1 GB of RAM each Root access on all machines This is a minimal setup, ideal for study, lab, or testing environments. For production, resources should be scaled according to expected load. Configuring the hosts file Before installing anything, it's important for the machines to resolve each other by name, not just by IP. Edit the /etc/hosts file on all servers and add the corresponding entries: 10 . 0 . 10 . 100 master . company . local master 10 . 0 . 10 . 101 slave01 . company . local slave01 10 . 0 . 10 . 102 slave02 . company . local slave02 This ensures that, later on, the Kubernetes components can correctly resolve node names. Configuring the Firewall Kubernetes depends on specific ports being open between nodes so the control-plane can communicate with the workers (and vice versa). The ports vary depending on the server's role in the cluster. On the master server: Port Protocol 6443 TCP 2379-2380 TCP 10250 TCP 10251 TCP 10252 TCP