Core Concepts
Before typing any commands, you must understand the mental model. It is critical to grasp the relationship between your local computer and the cloud server.
๐ป Local: Git
Git is a program installed on your computer. Think of it as an advanced Save Game system for code. Every time you finish a feature, you create a permanent "save point" (called a commit) that you can safely return to if things break.
โ๏ธ Cloud: Gitea
Gitea (gitea.mealno.in) is our private code website. It is the Cloud Backup for all your Git save points. Pushing code here allows teamwork and automatically tells Coolify to update the live website.
โก The 3 Stages of Saving
1. The Box
git add .Gather all the files you changed and put them into a box.
2. The Label
git commit -mTape the box shut permanently and stick a descriptive label on it.
3. The Truck
git pushSend the labeled box to our Gitea server so the team can see it.
One-Time Setup
Do this exactly ONCE per computer to install Git, configure line endings, and attach your identity.
Install Git
- Download from git-scm.com/downloads.
- Run installer, keep clicking Next.
- Search Windows/Mac for "Git Bash" to open the terminal.
Introduce Yourself & Configure
Git needs to know who is creating the save points, and we must fix Windows/Mac line-ending conflicts (CRLF vs LF).
# 1. Set your identity git config --global user.name "Your Name" git config --global user.email "your-email@mealno.in" # 2. Set default branch to main (not master) git config --global init.defaultBranch main # 3. Fix line endings (CRITICAL if team uses both Mac & Windows) # If on Windows: git config --global core.autocrlf true # If on Mac/Linux: git config --global core.autocrlf input # 4. Verify your settings git config --list
Start a New Project
Follow strictly in order when starting a blank local folder on your computer.
1. Navigate and Initialize
cd "C:/Users/Arnab/Desktop/MyWebsite" git init
2. Create .gitignore (CRITICAL)
Before you add any files, you MUST tell Git what to ignore. If you commit node_modules or .env, it will bloat the repository permanently.
# Create a .gitignore file and add standard exclusions
echo "node_modules/" >> .gitignore
echo ".env" >> .gitignore
echo "dist/" >> .gitignore
echo "build/" >> .gitignore
3. Create empty Gitea Repo
- Go to gitea.mealno.in -> Click + New Repository.
- Enter a Repository Name.
- UNCHECK "Initialize Repository". It MUST be empty!
- Click Create and copy the HTTPS URL.
4. Link & Push
# 1. Link the server (the "origin") git remote add origin https://gitea.mealno.in/USERNAME/REPO.git # 2. Stage and Commit files git add . git commit -m "Initial commit with .gitignore" # 3. Push to server (-u sets the default upstream tracking) git push -u origin main
The Daily Workflow
You will type these three commands dozens of times a week. Master this loop.
1. Stage
Packages all changed files. The dot . means "everything".
2. Commit
Permanently saves the box. You can use multiple -m flags for a Title and Description.
3. Push & Verify
git log --oneline -n 5
Uploads to Gitea (triggering Coolify). Use git log to verify the last 5 commits hit the server.
Syncing & Status
How to safely check your work and manage incoming changes from teammates.
โฌ๏ธ Pulling (Start of Day)
Rule #1: Before typing any code, download the latest changes. This prevents massive Merge Conflicts later.
๐ Fetching (Safe Check)
If you are scared pull will overwrite your work, use fetch. It downloads changes but doesn't apply them to your files yet.
git status
Stashing: The "Pause Game" Button
You're halfway through coding a feature, but an urgent bug comes in. You can't commit broken code, but you need to switch tasks. Stash it.
# 1. Hide your current messy work in a temporary drawer git stash -m "Half finished nav bar" # (Your files revert to the last clean commit automatically) # 2. ... fix the urgent bug, commit, push ... # 3. Bring your messy work back out of the drawer git stash pop
Branching & Teamwork
Never experiment on the live website. Use Branches.
feat/
New features (feat/login-page)
fix/
Bug fixes (fix/nav-crash)
hotfix/
Urgent live bug (hotfix/payment-error)
Modern Branch Workflow (git switch)
Note: git switch is the modern, safer alternative to the older git checkout.
# 1. Create a new branch and switch to it (-c means create) git switch -c feat/new-login-page # 2. Do your normal work (add, commit) git add . git commit -m "Build new login UI" # 3. Push this specific branch to the server git push -u origin feat/new-login-page
Handling Merge Conflicts
If you and a teammate edit the exact same line of code, Git throws a Conflict. Open VS Code. You will see colored highlights:
- Accept Current Change: Keep your edits.
- Accept Incoming Change: Keep your teammate's edits.
- Accept Both Changes: Keeps both, you edit them manually.
Click the button in VS Code, save the file, then run git add . and git commit -m "Resolve conflict".
Undoing Mistakes
Panic mode? Don't worry, Git is a time machine. Here is how to fix errors safely based on the exact situation.
๐งน 1. "I made a mess, throw it all away"
You broke files but haven't committed. You want everything back to how it was this morning.
# Discard changes to tracked files git restore . # Delete newly created (untracked) files/folders git clean -fd
๐ 2. "I committed, but I forgot a file"
You ran git commit but realized you missed something. This command undoes the commit but keeps your files intact so you can commit again.
git reset --soft HEAD~1
๐จ 3. "I pushed a bug to the live site!"
You need to roll back the entire live website. Always use Revert, never Reset. Revert safely creates a *new* commit that is the exact opposite of the bad one.
# 1. Find the bad commit ID (e.g., a1b2c3d) git log --oneline -n 5 # 2. Tell git to generate an inverse commit git revert a1b2c3d # 3. Push to fix the live site git push origin main
๐ Authentication & Tokens
Generate your Token:
- Log into gitea.mealno.in.
- Profile -> Settings -> Applications.
- Scroll to Manage Access Tokens.
- Name it (e.g. "Work Laptop").
- Check
repositorypermission. - Generate and copy it immediately.
Token Expiration
Enterprise policy dictates tokens should not live forever. When generating, set an expiration of 90 Days.
When it expires, your git push will fail with a 403 error. Simply generate a new token and update your URL.
๐ก Hardcoding the Token (Private PC Only)
To stop typing the token every time you push, embed it in the URL. Never do this on a shared computer.
git remote set-url origin https://USERNAME:TOKEN_GOES_HERE@gitea.mealno.in/USERNAME/PROJECT.git
Clearing Stale Passwords
If Windows/Mac cached your old password and refuses to ask for the new Token, clear the cache:
# Windows: Open Start Menu -> "Credential Manager" -> "Windows Credentials" -> Delete the git entry. # Mac: Open "Keychain Access" -> Search "git" -> Delete the entry. # Universal Terminal fallback: git credential-manager reject https://gitea.mealno.in
Deploying with Coolify
Coolify pulls code from Gitea, builds it into a Docker container, and puts it live on the internet.
1. Create Resource (Nixpacks vs Dockerfile)
Log into Coolify. Click + New Resource -> Application -> Gitea.
2. Connect Code
Select exact repo (e.g., mealno/frontend).
Type main.
3. Build Configuration (Crucial)
npm run build
build (or dist)
3000
18
Zero-Downtime Deployments (Healthcheck)
To prevent the site dropping offline while restarting, configure the Healthcheck tab:
- Path:
/(or/api/healthfor backend) - Coolify will wait until this URL returns 200 OK before shutting down the old container.
4. Domain & Deploy
Type your domain (e.g. https://mealno.in). Coolify generates SSL automatically via Let's Encrypt. Click Deploy.
Environment Variables (.env)
The only secure way to handle API keys, database passwords, and config.
๐จ NEVER commit secrets to Git
If you hardcode an API key in api.js and push it, it lives in the git history forever. You must use the dotenv library and store them in a .env file.
Build-Time Variables
Variables baked into HTML/JS during npm build (like React frontend URLs). Anyone can see these in the browser console.
REACT_APP_API_URL=https://api.mealno.in
NEXT_PUBLIC_STRIPE_KEY=pk_test_123
Run-Time Variables (Secrets)
Variables kept purely on the Node.js/Python backend server. These are true secrets.
DATABASE_URL=postgres://user:pass@db:5432
JWT_SECRET=super_secure_random_string
Production Secrets (Coolify)
Since the live server doesn't have your local .env file, you must inject them via Coolify:
- Open Project in Coolify -> Click Environment Variables tab.
- Click + Add.
- Key:
DATABASE_URL| Value:postgres://... - Check "Is Build Env?" ONLY if it is a Build-Time variable (like React).
- Check "Is Secret?" to hide it from UI logs.
- Click Save -> Click Redeploy (required to bake them into the build).
Managing Coolify
๐๏ธ Monthly Docker Cleanup
Old deployments fill the hard drive until the server crashes at 100%.
โฌ๏ธ Coolify Updates
Watch the bottom-left sidebar. Click "Update Available". The UI freezes for 2 mins. Live sites stay online.
๐พ Instance Backups (S3)
You must back up Coolify's internal database (which holds all your env vars and configs) to an external cloud like AWS S3.
- Coolify Settings -> S3 Destinations -> Add AWS Credentials.
- Go to Instance Backups -> Select the S3 bucket.
- Set cron to
0 0 * * *(Daily at midnight).
DBs & Backups
Deploying a Database
Coolify makes DB deployment a 1-click process.
- Click + New Resource -> Database.
- Select Engine (e.g., PostgreSQL, MySQL, Redis).
- Coolify generates secure passwords automatically. Click Start.
Connection String URI Formats:
# Postgres: postgresql://user:password@hostname:5432/dbname
# MySQL: mysql://user:password@hostname:3306/dbname
# Redis: redis://:password@hostname:6379
Automated Backups
Never run a production DB without backups configured.
- Open your Database resource in Coolify.
- Go to the Backups tab.
- Set Schedule (e.g.,
0 0 * * *for daily at midnight). - Select Destination (Local Server, or configure S3 for cloud backup).
App Architecture
How code travels from your laptop to the live domain, and how containers talk to each other.
1. Developer
Runs git push
2. Gitea
Saves code & fires a Webhook
3. Coolify
Builds Docker container
4. Live Server
Traefik applies SSL/HTTPS
Internal Container Networking
Containers running on the same server (like a Node API and a Postgres DB) do not need to route out to the public internet to talk to each other. They use the Internal Docker Network.
If your Database container in Coolify is named db-postgres-1, your Node app's environment variable should be:
DATABASE_URL=postgres://user:pass@db-postgres-1:5432/dbname
Notice how we use the container name instead of "localhost" or an IP address. Docker DNS resolves this automatically.
DNS & Ports
๐ DNS (Cloudflare)
Translates names to IPs.
- A Record Points a domain (mealno.in) to an IPv4 address (192.168.1.1).
- Orange Cloud (Proxied): Cloudflare hides your real IP and stops DDoS attacks.
- Grey Cloud (DNS Only): Connects directly. Required for SSH access.
๐ช Ports & Protocols
TCP: Reliable, verifies delivery (Web, DB, SSH).UDP: Fast, drops packets (Video streaming, Games).
The Reverse Proxy (Traefik)
If 5 containers run on one server, who answers Port 443? The Reverse Proxy. It acts as a Traffic Cop.
(Internal Port 3000)
(Internal Port 8000)
Server Hardening
Raw Linux servers are brute-forced by bots within minutes. Secure it immediately.
1. Disable Password SSH Login
Passwords can be brute-forced. SSH Keys cannot. Generate a key, add it to the server, and disable passwords entirely.
ssh-keygen -t ed25519 -C "admin@mealno.in" # Copy the output key to the server's ~/.ssh/authorized_keys
PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes
sudo systemctl restart sshd
2. Uncomplicated Firewall (UFW)
Block all ports except the ones you explicitly need.
# CRITICAL: Allow SSH BEFORE enabling firewall sudo ufw allow 22 # Allow Web Traffic sudo ufw allow 80 sudo ufw allow 443 sudo ufw enable
3. Fail2Ban
A service that monitors logs. If an IP fails to login via SSH 5 times, it permanently bans that IP at the firewall level. Configured in /etc/fail2ban/jail.local.
Advanced Secrets
Manually copying `.env` files across a team of 10 developers leads to leaks.
External Secret Managers (Doppler)
Enterprise teams use centralized vaults like Doppler, HashiCorp Vault, or AWS Secrets Manager.
Using Doppler Locally
Instead of a `.env` file, developers authenticate with the Doppler CLI. It injects the secrets directly into the run command:
doppler run -- npm run dev
Secret Rotation
Database passwords and API keys should be changed (rotated) every 90 days. If an employee leaves, keys must be rotated immediately to revoke access.
Monitoring & Logs
Observability means knowing the internal state of your system just by looking at its outputs.
The 4 Golden Signals
Latency
Time to serve request
Traffic
Total requests/sec
Errors
Rate of failing requests
Saturation
CPU/RAM limits
Uptime Kuma (Beginner)
Pings a URL every 60 seconds. Deploy it via Docker:
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1
Prometheus (Enterprise)
Pulls deep metrics. You write PromQL queries to build Grafana dashboards.
# PromQL Example: Server 500 Errors rate(http_requests_total{status="500"}[5m])
Centralized Logs (ELK/Loki)
Running docker logs is fine for 1 app. If you have 10 microservices, you need a central tool (like Grafana Loki) to search all logs simultaneously, retaining them for compliance.
Alerting Systems
Metrics are useless if nobody looks at them. Alerts wake you up when things break.
Discord Webhooks
Go to Channel Settings -> Integrations -> Webhooks. Your monitoring tool sends a POST request here.
"content": "๐จ mealno.in is DOWN"
}
PagerDuty Escalation
For critical apps, tools like PagerDuty handle "On-Call Rotations".
- P3 Slack message. Wait 5m.
- P2 SMS the developer. Wait 5m.
- P1 Call CTO's phone physically.
๐จ Emergency Playbook
Website down? Don't panic. Work through this checklist in order. Stop when you find the issue.
1 Can you load the Coolify Dashboard?
YES - It loads: Hardware is fine. The app crashed. Go to Coolify -> Project -> Logs. Click Restart.
NO - Won't load: Server is dead (CPU lock or OOM). Hard Reboot via Hetzner/AWS panel.
dmesg -T | grep -i oom
2 Did a recent deployment break it?
Check the Deployments tab in Coolify. Look for a red "failed" status. Find the previous green deployment below it, click the three dots, and hit Redeploy to instantly roll back.
3 Are you seeing a 502 Bad Gateway?
Traefik is alive, but your app container is dead or not listening. Check your Coolify Port configuration (ensure it matches your app's actual exposed port, e.g., 3000 vs 8000).
4 Is it a DNS issue? (NXDOMAIN)
If browser says "Site Cannot Be Reached": Check domain registrar. Use ping mealno.in. To bypass Cloudflare and test the server directly, edit your laptop's local hosts file:
192.168.1.50 mealno.in