Assistant System Administrator ยท WorldLink Communication
I keep production infrastructure up, quiet, and boring โ VoIP trunks, container clusters, log pipelines, and the reverse proxies in front of them.
$ cat about.txt
Looking for a challenging career with real scope to demonstrate what I can do โ I'm drawn to bigger outlooks, thriving on imagination and passion, and setting a standard that exceeds expectations.
A fun attitude at work is everything, and I'm a learner for life. Most days that means keeping VoIP trunks connected, containers healthy, and logs searchable โ quietly, before anyone notices something was wrong.
$ history --job -n 3
$ ls -la ~/skills/ โ click any to inspect
Systems & Virtualization
Containers & Orchestration
Telephony & Messaging
Observability & Logging
Networking & Service Infra
Network Ops
$ cat docs/*.md โ full install & config notes
Complete step-by-step installation and working configuration examples for the production stack I run daily.
# Download and run the official install script curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # Add your user to the docker group (so you don't need sudo) sudo usermod -aG docker $USER # Log out and log back in, or run: newgrp docker # Start and enable Docker sudo systemctl enable --now docker # Verify installation docker version docker run --rm hello-world
# Replace 10.10.10.1 with the IP other nodes can reach docker swarm init --advertise-addr 10.10.10.1 # Get the worker join command docker swarm join-token worker # On every worker node run the join command, for example: docker swarm join --token SWMTKN-1-xxxxx 10.10.10.1:2377 # Check cluster status docker node ls docker info | grep -A 10 Swarm
version: "3.8"
services:
web:
image: nginx:1.25-alpine
ports:
- target: 80
published: 80
protocol: tcp
mode: ingress
volumes:
- web_data:/usr/share/nginx/html:ro
deploy:
mode: replicated
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
order: start-first
rollback_config:
parallelism: 1
delay: 5s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
resources:
limits:
cpus: "0.50"
memory: 128M
reservations:
cpus: "0.25"
memory: 64M
networks:
- frontend
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
interval: 15s
timeout: 5s
retries: 3
redis:
image: redis:7-alpine
command: >
redis-server
--requirepass StrongRedisPass123
--maxmemory 256mb
--maxmemory-policy allkeys-lru
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
networks:
- backend
volumes:
- redis_data:/data
networks:
frontend:
driver: overlay
backend:
driver: overlay
volumes:
web_data:
redis_data:
# Deploy docker stack deploy -c docker-compose.yml prod # List services docker service ls # Inspect a service docker service ps prod_web docker service logs -f prod_web # Scale docker service scale prod_web=5 # Update image with rolling update docker service update --image nginx:1.26-alpine prod_web # Remove stack docker stack rm prod
Official docs โ Docker Engine Install ยท Swarm mode ยท Compose
# Debian / Ubuntu packages sudo apt update sudo apt install -y kannel # Create log directory if missing sudo mkdir -p /var/log/kannel sudo chown kannel:kannel /var/log/kannel # Enable and start sudo systemctl enable kannel sudo systemctl start kannel sudo systemctl status kannel
group = core admin-port = 13000 smsbox-port = 13001 admin-password = StrongAdminPass status-password = StatusPass123 admin-deny-ip = "*.*.*.*" admin-allow-ip = "127.0.0.1;10.*.*.*" log-file = /var/log/kannel/bearerbox.log log-level = 0 box-deny-ip = "*.*.*.*" box-allow-ip = "127.0.0.1" access-log = /var/log/kannel/access.log # SMSC connection (SMPP example) group = smsc smsc = smpp smsc-id = provider1 host = smpp.provider.com port = 2775 smsc-username = your_smpp_user smsc-password = your_smpp_pass system-type = address-range = transceiver-mode = true enquire-link-interval = 30 reconnect-delay = 10 source-addr-ton = 1 source-addr-npi = 1 dest-addr-ton = 1 dest-addr-npi = 1 # SMSBox group = smsbox bearerbox-host = 127.0.0.1 bearerbox-port = 13001 sendsms-port = 13013 sendsms-chars = "0123456789 +-" log-file = /var/log/kannel/smsbox.log log-level = 0 access-log = /var/log/kannel/smsbox-access.log mo-recode = true # sendsms-user (HTTP API) group = sendsms-user username = smsuser password = SmsApiPass123 user-deny-ip = "*.*.*.*" user-allow-ip = "127.0.0.1;10.*.*.*" max-messages = 10 concatenation = true # Default SMS service (optional DLR) group = sms-service keyword = default text = "Message received" max-messages = 0 accept-x-kannel-headers = true
# Restart after config change sudo systemctl restart kannel # Check status via admin interface curl "http://127.0.0.1:13000/status?password=StatusPass123" # Send a test SMS via HTTP API curl "http://127.0.0.1:13013/cgi-bin/sendsms?\ username=smsuser&\ password=SmsApiPass123&\ to=97798XXXXXXXX&\ from=SenderID&\ text=Hello%20from%20Kannel" # Watch logs sudo tail -f /var/log/kannel/bearerbox.log sudo tail -f /var/log/kannel/smsbox.log
Official docs โ Kannel Download ยท Kannel User Guide
# Import GPG key wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg # Add repo (Debian/Ubuntu example) echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | \ sudo tee /etc/apt/sources.list.d/elastic-8.x.list sudo apt update sudo apt install -y elasticsearch logstash kibana # Enable services sudo systemctl enable elasticsearch logstash kibana
cluster.name: wlink-logs node.name: node-1 path.data: /var/lib/elasticsearch path.logs: /var/log/elasticsearch network.host: 0.0.0.0 http.port: 9200 discovery.type: single-node # For production later: enable security xpack.security.enabled: false xpack.security.http.ssl.enabled: false
sudo systemctl start elasticsearch # Wait ~20-30 seconds then: curl -X GET "http://localhost:9200/" curl -X GET "http://localhost:9200/_cluster/health?pretty"
input {
beats {
port => 5044
}
}
filter {
if [fields][log_type] == "nginx" {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
if [fields][log_type] == "syslog" {
grok {
match => { "message" => "%{SYSLOGTIMESTAMP:timestamp} %{SYSLOGHOST:host} %{DATA:program}(?:\[%{POSINT:pid}\])?: %{GREEDYDATA:syslog_message}" }
}
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "logs-%{[fields][log_type]}-%{+YYYY.MM.dd}"
}
# Uncomment for debugging
# stdout { codec => rubydebug }
}
server.port: 5601 server.host: "0.0.0.0" elasticsearch.hosts: ["http://localhost:9200"] logging.appenders.file.type: file logging.appenders.file.fileName: /var/log/kibana/kibana.log logging.appenders.file.layout.type: json
sudo systemctl start logstash sudo systemctl start kibana # Check sudo systemctl status elasticsearch logstash kibana curl http://localhost:5601/api/status
Official docs โ Elasticsearch ยท Logstash ยท Kibana
sudo apt update sudo apt install -y nginx sudo systemctl enable --now nginx nginx -v
upstream backend_app {
least_conn;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name app.example.com;
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
access_log /var/log/nginx/app.access.log;
error_log /var/log/nginx/app.error.log;
client_max_body_size 20M;
location / {
proxy_pass http://backend_app;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location /health {
access_log off;
return 200 "ok\n";
add_header Content-Type text/plain;
}
}
sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx # Optional: certbot for Let's Encrypt sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d app.example.com
Official docs โ Nginx Documentation ยท Proxy module
# Create network docker network create traefik-public # traefik.yml (static config) # Save as /opt/traefik/traefik.yml
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik-public
file:
directory: /etc/traefik/dynamic
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
log:
level: INFO
docker run -d \ --name traefik \ --restart unless-stopped \ -p 80:80 -p 443:443 \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /opt/traefik/traefik.yml:/etc/traefik/traefik.yml:ro \ -v /opt/traefik/letsencrypt:/letsencrypt \ -v /opt/traefik/dynamic:/etc/traefik/dynamic \ --network traefik-public \ traefik:v3.0
services:
myapp:
image: myapp:latest
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
- "traefik.http.services.myapp.loadbalancer.server.port=8080"
- "traefik.docker.network=traefik-public"
Official docs โ Traefik Documentation ยท Docker provider
sudo apt update sudo apt install -y redis-server sudo systemctl enable redis-server
# Bind only to localhost (or private IP) bind 127.0.0.1 # Require password requirepass StrongRedisPassHere123 # Persistence appendonly yes appendfsync everysec # Memory management maxmemory 512mb maxmemory-policy allkeys-lru # Security / performance protected-mode yes tcp-backlog 511 timeout 0 tcp-keepalive 300 # Logging loglevel notice logfile /var/log/redis/redis-server.log # supervised by systemd supervised systemd
sudo systemctl restart redis-server sudo systemctl status redis-server # Test auth redis-cli > AUTH StrongRedisPassHere123 > PING PONG > SET test "hello" > GET test > INFO memory
# /etc/systemd/system/redis-server.service.d/override.conf [Service] LimitNOFILE=65535 sudo systemctl daemon-reload sudo systemctl restart redis-server
Official docs โ Redis Install ยท Configuration
# Download latest from HashiCorp
VER=1.20.0
curl -fsSL https://releases.hashicorp.com/consul/${VER}/consul_${VER}_linux_amd64.zip -o consul.zip
sudo apt install -y unzip
unzip consul.zip
sudo mv consul /usr/local/bin/
consul version
# Create user and directories
sudo useradd --system --home /etc/consul.d --shell /bin/false consul
sudo mkdir -p /etc/consul.d /var/lib/consul
sudo chown -R consul:consul /etc/consul.d /var/lib/consul
server = true
bootstrap_expect = 1
data_dir = "/var/lib/consul"
client_addr = "0.0.0.0"
bind_addr = "10.10.10.1" # this node's IP
advertise_addr = "10.10.10.1"
ui_config {
enabled = true
}
connect {
enabled = true
}
ports {
grpc = 8502
}
log_level = "INFO"
enable_syslog = true
[Unit] Description=HashiCorp Consul Requires=network-online.target After=network-online.target [Service] User=consul Group=consul ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
sudo systemctl enable --now consul
consul members
# Register a service via HTTP API
curl -X PUT -d '{
"Name": "web",
"ID": "web-1",
"Address": "10.10.10.5",
"Port": 80,
"Check": {
"HTTP": "http://10.10.10.5/health",
"Interval": "10s",
"Timeout": "2s"
}
}' http://127.0.0.1:8500/v1/agent/service/register
# Query
curl http://127.0.0.1:8500/v1/catalog/services
curl http://127.0.0.1:8500/v1/health/service/web?pass
Official docs โ Consul Install ยท Consul Documentation
VER=2.54.1
curl -fsSL https://github.com/prometheus/prometheus/releases/download/v${VER}/prometheus-${VER}.linux-amd64.tar.gz -o prometheus.tar.gz
tar xzf prometheus.tar.gz
cd prometheus-${VER}.linux-amd64
sudo useradd --system --no-create-home --shell /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo cp prometheus promtool /usr/local/bin/
sudo cp -r consoles console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: []
rule_files: []
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "node"
static_configs:
- targets: ["localhost:9100"]
- job_name: "docker"
static_configs:
- targets: ["localhost:9323"]
- job_name: "nginx"
static_configs:
- targets: ["localhost:9113"]
# /etc/systemd/system/prometheus.service [Unit] Description=Prometheus Wants=network-online.target After=network-online.target [Service] User=prometheus Group=prometheus Type=simple ExecStart=/usr/local/bin/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus \ --web.console.templates=/etc/prometheus/consoles \ --web.console.libraries=/etc/prometheus/console_libraries \ --web.listen-address=0.0.0.0:9090 Restart=on-failure [Install] WantedBy=multi-user.target # Then: sudo systemctl daemon-reload sudo systemctl enable --now prometheus
VER=1.8.2
curl -fsSL https://github.com/prometheus/node_exporter/releases/download/v${VER}/node_exporter-${VER}.linux-amd64.tar.gz | tar xz
sudo cp node_exporter-${VER}.linux-amd64/node_exporter /usr/local/bin/
sudo useradd -rs /bin/false node_exporter
# Simple systemd unit
cat <
5. Install Grafana
# Official apt repo
sudo apt install -y apt-transport-https software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/grafana.gpg
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://packages.grafana.com/oss/deb stable main" | \
sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo systemctl enable --now grafana-server
# Default login: admin / admin โ change immediately
# UI: http://YOUR_IP:3000
6. Add Prometheus data source in Grafana
# Via UI: Configuration โ Data sources โ Add โ Prometheus
# URL: http://localhost:9090
# Or via provisioning file /etc/grafana/provisioning/datasources/prometheus.yml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://localhost:9090
isDefault: true
editable: false
Official docs โ Prometheus Install ยท Node Exporter ยท Grafana Install
$ cat contact.txt