[{"data":1,"prerenderedAt":1623},["ShallowReactive",2],{"search-posts-dataset":3,"post-detail-/posts/backup-postgres-docker":159,"all-published-articles-list":1559,"series-posts-/posts/backup-postgres-docker":1619},[4,20,35,48,62,75,87,99,111,122,135,149],{"path":5,"title":6,"description":7,"categories":8,"tags":11,"date":16,"image":17},"/posts/incident-checklist","Checklist xử lí sự cố máy chủ Linux: Phục hồi sau thảm họa","Qui trình phản ứng và xử lí sự cố máy chủ Linux khi hệ thống bị sập, tràn RAM/HDD hoặc nghi ngờ bị xâm nhập: Các bước chuẩn đoán, cô lập, phân tích log và khôi phục.",[9,10],"linux","devops",[12,13,14,15],"incident","troubleshooting","security","sysadmin","2026-08-15T00:00:00.000Z",{"src":18,"alt":19},"/img/incident-response.webp","Xử lí sự cố máy chủ Linux",{"path":21,"title":22,"description":23,"categories":24,"tags":27,"date":31,"image":32},"/posts/backup-postgres-docker","Sao lưu tự động PostgreSQL trong Docker với cron job và gzip","Hướng dẫn xây dựng script tự động backup database PostgreSQL chạy trong Docker container: gzip, cron hàng ngày, tự động xóa bản sao lưu cũ và kiểm thử phục hồi.",[25,26],"docker","database",[28,29,30,10],"postgresql","backup","automation","2025-10-20T00:00:00.000Z",{"src":33,"alt":34},"/img/postgres-backup.webp","Sao lưu tự động PostgreSQL Docker",{"path":36,"title":37,"description":38,"categories":39,"tags":40,"date":44,"image":45},"/posts/docker-compose-production","Thiết kế Docker compose chuẩn Production","Hướng dẫn thực chiến xây dựng docker-compose.yml hoàn chỉnh cho Production: healthchecks, restart policies, resource limits, quản lí .env và Persistent Volumes",[25,10],[41,42,43],"production","compose","backend","2025-10-15T00:00:00.000Z",{"src":46,"alt":47},"/img/docker-compose.webp","Docker Compose Production Best Practices",{"path":49,"title":50,"description":51,"categories":52,"tags":53,"date":58,"image":59},"/posts/monitoring-server-basics","Giám sát server Linux từ cơ bản đến nâng cao: htop, ncdu, prometheus và Uptime Kuma","Cẩm nang toàn diện về giám sát hiệu năng máy chủ Linux: Khai thác công cụ CLI thời gian thực (Htop, Btop, Ncdu), thiết lập hệ thống cảnh báo sự cố Uptime Kuma qua Telegram và thu thập chỉ số với Prometheus & Grafana.",[9,10],[54,55,56,57],"monitoring","grafana","prometheus","uptime","2024-10-18T00:00:00.000Z",{"src":60,"alt":61},"/img/monitoring.webp","Giám sát máy chủ Linux",{"path":63,"title":64,"description":65,"categories":66,"tags":68,"date":71,"image":72},"/posts/nginx-reverse-proxy","Hướng dẫn cấu hình Nginx Reverse Proxy với SSL Certbot và Docker chuẩn Production","Cẩm nang toàn diện cấu hình Nginx Reverse Proxy trên Ubuntu: Tích hợp chứng chỉ SSL Let's Encrypt miễn phí qua Certbot, hỗ trợ WebSockets, HTTP/2, nén Brotli/Gzip và Rate Limiting chống DDoS.",[9,67],"nginx",[10,69,70],"ssl","webserver","2024-10-10T00:00:00.000Z",{"src":73,"alt":74},"/img/nginx.webp","Nginx Reverse Proxy với SSL",{"path":76,"title":77,"description":78,"categories":79,"tags":80,"date":83,"image":84},"/posts/how-to-secure-a-vps","Bảo mật máy chủ Linux VPS: Cẩm nang toàn diện 8 bước chống tấn công","Hướng dẫn thực chiến từng bước thiết lập bảo mật máy chủ Linux VPS mới: Vô hiệu hóa mật khẩu SSH, thiết lập SSH Key Ed25519, cấu hình Fail2ban, tường lửa UFW và cập nhật tự động Unattended-Upgrades.",[9,14],[81,82,10],"vps","hardening","2024-10-05T00:00:00.000Z",{"src":85,"alt":86},"/img/linux-security.webp","Bảo mật máy chủ Linux VPS",{"path":88,"title":89,"description":90,"categories":91,"tags":92,"date":95,"image":96},"/posts/systemd-node-service","Quản lí ứng dụng Node.js trong Production với Systemd Service và Journalctl","Hướng dẫn triển khai ứng dụng Node.js, Go hoặc Python dưới dạng Systemd Service trên Linux: Tự động khởi động lại khi crash, quản lý biến môi trường, giới hạn bộ nhớ RAM và theo dõi log thời gian thực với Journalctl.",[9,10],[93,94,43,41],"systemd","nodejs","2024-10-01T00:00:00.000Z",{"src":97,"alt":98},"/img/systemd.webp","Quản lý ứng dụng với Systemd Service",{"path":100,"title":101,"description":102,"categories":103,"tags":104,"date":107,"image":108},"/posts/how-to-install-docker-on-ubuntu-server","Hướng dẫn cài đặt Docker & Docker compose trên Ubuntu server","Hướng dẫn toàn diện cách cài đặt Docker Engine và Docker Compose V2 trên Ubuntu Server, cấu hình bảo mật non-root user, tối ưu daemon và xử lí xung đột tường lửa UFW",[9,25],[105,10,106],"beginner","ubuntu","2024-09-30T00:00:00.000Z",{"src":109,"alt":110},"/img/docker.webp","Cài đặt Docker trên Ubuntu Server",{"path":112,"title":113,"description":114,"categories":115,"tags":116,"date":118,"image":119},"/posts/ssh-key-authentication","Xác thực SSH Key từ cơ bản đến nâng cao: Ed25519, SSH Config và Bảo mật đa tầng","Cẩm nang toàn diện về xác thực SSH Key trên máy chủ Linux: So sánh Ed25519 vs RSA, cấu hình SSH Config quản lí hàng chục VPS, chuyển tiếp Agent Forwarding, và các qui tắc bảo mật chống lộ khóa.",[9,14],[117,10,15],"ssh","2024-09-25T00:00:00.000Z",{"src":120,"alt":121},"/img/ssh-keys.webp","Xác thực SSH Key Linux",{"path":123,"title":124,"description":125,"categories":126,"tags":127,"date":131,"image":132},"/posts/ufw-firewall-basics","Làm chủ tường lửa UFW trên Linux: Qui tắc, giới hạn kết nối và xử lí xung đột Docker","Hướng dẫn toàn diện làm chủ tường lửa UFW (Uncomplicated Firewall) trên Ubuntu: Thiết lập chính sách mặc định, mở cổng theo IP, giới hạn brute-force (Rate Limiting) và khắc phục lỗi Docker bypass tường lửa.",[9,14],[128,129,130,15],"ufw","firewall","networking","2024-09-20T00:00:00.000Z",{"src":133,"alt":134},"/img/ufw-firewall.webp","Cấu hình Tường lửa UFW Linux",{"path":136,"title":137,"description":138,"categories":139,"tags":141,"date":145,"image":146},"/posts/git-deploy-key","Tự động hóa triển khai với Git deploy keys: Thiết lập an toàn cho GitHub và GitLab","Hướng dẫn thiết lập Git Deploy Key chuẩn bảo mật để kéo mã nguồn tự động từ GitHub hoặc GitLab về máy chủ Production: Phân quyền Read-Only, cấu hình SSH Config và tích hợp Webhook tự động cập nhật.",[140,10],"git",[142,143,144,30],"github","gitlab","cicd","2024-09-18T00:00:00.000Z",{"src":147,"alt":148},"/img/git-deploy.webp","Git Deploy Keys cho máy chủ",{"path":150,"title":151,"description":152,"categories":153,"tags":154,"date":155,"image":156},"/posts/ubuntu-server-initial-setup","Qui trình thiết lập ban đầu cho Ubuntu Server: Swap, Timezone, User và Firewall","Hướng dẫn các bước thiết lập chuẩn mực ban đầu cho máy chủ Ubuntu Server mới: Cấu hình múi giờ Việt Nam (Asia/Ho_Chi_Minh), tạo phân vùng RAM ảo (Swap File), phân quyền Sudoer và kích hoạt tường lửa UFW.",[9],[106,105,15],"2024-09-15T00:00:00.000Z",{"src":157,"alt":158},"/img/ubuntu.webp","Thiết lập ban đầu Ubuntu Server",{"id":160,"title":22,"author":161,"body":162,"categories":1547,"date":31,"description":23,"draft":1548,"extension":1549,"image":1550,"meta":1551,"navigation":441,"path":21,"seo":1552,"series":1553,"series_order":421,"slug":1554,"stem":1555,"tags":1556,"updated":1557,"__hash__":1558},"post/posts/backup-postgres-docker.md","Dương Thụ",{"type":163,"value":164,"toc":1532},"minimal",[165,170,174,181,189,199,202,214,223,226,302,330,332,340,343,378,385,400,403,1017,1024,1039,1041,1045,1048,1059,1062,1078,1081,1094,1096,1100,1107,1112,1127,1130,1147,1161,1164,1178,1180,1184,1187,1192,1198,1245,1252,1353,1355,1359,1362,1379,1429,1431,1435,1515,1517,1521,1528],[166,167,169],"h2",{"id":168},"tầm-quan-trọng-của-chiến-lược-sao-lưu-dữ-liệu-backup-strategy","Tầm quan trọng của chiến lược sao lưu dữ liệu (Backup Strategy)",[171,172,173],"p",{},"Dữ liệu là tài sản quan trọng nhất của bất kì hệ thống phần mềm nào. Cho dù bạn có thiết lập hệ thống mạnh mẽ đến đâu, các sự cố như lỗi phần cứng ổ đĩa, thao tác xóa nhầm của con người, lỗi migration cơ sở dữ liệu hoặc tấn công mã độc ransomware vẫn luôn có thể xảy ra....",[171,175,176,177],{},"Một nguyên tắc vàng trong quản trị hệ thống là: ",[178,179,180],"strong",{},"Một bản sao lưu chưa từng được kiểm tra khôi phục thì không được coi là một bản sao lưu (An untested backup is not a backup).",[171,182,183,184,188],{},"Trong bài viết này, chúng ta sẽ cùng nhau xây dựng một giải pháp sao lưu tự động, nén dữ liệu, dọn dẹp các bản backup cũ và phục hồi toàn diện cho cơ sở dữ liệu PostgreSQL đang chạy dưới dạng ",[185,186,187],"a",{"href":100},"Docker"," container..",[190,191,193],"info-box",{"type":192},"tip",[171,194,195,198],{},[178,196,197],{},"Mẹo hữu ích:"," Bạn có thể sử dụng phím tắt hoặc tham số dòng lệnh để tối ưu tốc độ.",[200,201],"hr",{},[166,203,205,206,210,211],{"id":204},"_1-nguyên-lí-hoạt-động-của-docker-exec-và-pg_dump","1. Nguyên lí hoạt động của ",[207,208,209],"code",{},"docker exec"," và ",[207,212,213],{},"pg_dump",[171,215,216,217,219,220,222],{},"Thay vì phải cài đặt các công cụ PostgreSQL client trên máy chủ chủ (Host OS), chúng ta có thể tận dụng chính tiện ích ",[207,218,213],{}," đã có sẵn bên trong container PostgreSQL bằng lệnh ",[207,221,209],{},".",[171,224,225],{},"Lệnh sao lưu cốt lõi có dạng:",[227,228,233],"pre",{"className":229,"code":230,"language":231,"meta":232,"style":232},"language-bash shiki shiki-themes github-dark github-dark github-dark","docker exec -t \u003CCONTAINER_NAME> pg_dump -U \u003CDB_USER> \u003CDB_NAME> | gzip > /path/to/backup/db_backup.sql.gz\n","bash","",[207,234,235],{"__ignoreMap":232},[236,237,240,243,247,251,255,258,262,265,268,271,273,276,279,281,283,286,288,290,293,296,299],"span",{"class":238,"line":239},"line",1,[236,241,25],{"class":242},"sb7EE",[236,244,246],{"class":245},"skqr8"," exec",[236,248,250],{"class":249},"sKJT9"," -t",[236,252,254],{"class":253},"sWuGj"," \u003C",[236,256,257],{"class":245},"CONTAINER_NAM",[236,259,261],{"class":260},"sFJ4l","E",[236,263,264],{"class":253},">",[236,266,267],{"class":245}," pg_dump",[236,269,270],{"class":249}," -U",[236,272,254],{"class":253},[236,274,275],{"class":245},"DB_USE",[236,277,278],{"class":260},"R",[236,280,264],{"class":253},[236,282,254],{"class":253},[236,284,285],{"class":245},"DB_NAM",[236,287,261],{"class":260},[236,289,264],{"class":253},[236,291,292],{"class":253}," |",[236,294,295],{"class":242}," gzip",[236,297,298],{"class":253}," >",[236,300,301],{"class":245}," /path/to/backup/db_backup.sql.gz\n",[303,304,305,314,322],"ul",{},[306,307,308,313],"li",{},[178,309,310],{},[207,311,312],{},"-t",": Cấp quyền TTY ảo để nhận dữ liệu luồng.",[306,315,316,321],{},[178,317,318],{},[207,319,320],{},"pg_dump -U \u003Cuser> \u003Cdb>",": Xuất cấu trúc và toàn bộ dữ liệu bảng dưới dạng mã SQL.",[306,323,324,329],{},[178,325,326],{},[207,327,328],{},"| gzip",": Nén luồng dữ liệu ngay lập tức trên RAM trước khi ghi xuống đĩa, giúp tiết kiệm tới 80-90% dung lượng ổ cứng.",[200,331],{},[166,333,335,336,339],{"id":334},"_2-viết-script-sao-lưu-tự-động-chuyên-nghiệp-backup_postgressh","2. Viết Script Sao lưu tự động chuyên nghiệp (",[207,337,338],{},"backup_postgres.sh",")",[171,341,342],{},"Tạo một thư mục chuyên dụng chứa các script quản trị trên máy chủ:",[227,344,346],{"className":229,"code":345,"language":231,"meta":232,"style":232},"sudo mkdir -p /opt/scripts /var/backups/postgres\nsudo chmod 700 /var/backups/postgres\n",[207,347,348,365],{"__ignoreMap":232},[236,349,350,353,356,359,362],{"class":238,"line":239},[236,351,352],{"class":242},"sudo",[236,354,355],{"class":245}," mkdir",[236,357,358],{"class":249}," -p",[236,360,361],{"class":245}," /opt/scripts",[236,363,364],{"class":245}," /var/backups/postgres\n",[236,366,368,370,373,376],{"class":238,"line":367},2,[236,369,352],{"class":242},[236,371,372],{"class":245}," chmod",[236,374,375],{"class":249}," 700",[236,377,364],{"class":245},[171,379,380,381,384],{},"Tạo file script ",[207,382,383],{},"/opt/scripts/backup_postgres.sh",":",[227,386,388],{"className":229,"code":387,"language":231,"meta":232,"style":232},"sudo nano /opt/scripts/backup_postgres.sh\n",[207,389,390],{"__ignoreMap":232},[236,391,392,394,397],{"class":238,"line":239},[236,393,352],{"class":242},[236,395,396],{"class":245}," nano",[236,398,399],{"class":245}," /opt/scripts/backup_postgres.sh\n",[171,401,402],{},"Dán nội dung script hoàn chỉnh dưới đây:",[227,404,406],{"className":229,"code":405,"language":231,"meta":232,"style":232},"#!/bin/bash\n# ==============================================================================\n# SCRIPT TỰ ĐỘNG SAO LƯU POSTGRESQL TRONG DOCKER\n# Tác giả: TechBlog Admin\n# ==============================================================================\n\nset -eo pipefail\n\n# Cấu hình thông tin\nCONTAINER_NAME=\"production_postgres\"\nDB_USER=\"pgadmin\"\nDB_NAME=\"core_production\"\nBACKUP_DIR=\"/var/backups/postgres\"\nDATE_STAMP=$(date +\"%Y%m%d_%H%M%S\")\nFILENAME=\"${BACKUP_DIR}/${DB_NAME}_${DATE_STAMP}.sql.gz\"\nLOG_FILE=\"/var/log/postgres_backup.log\"\nRETENTION_DAYS=7 # Lưu trữ tối đa trong 7 ngày\n\nlog_message() {\n    echo \"[$(date '+%Y-%m-%d %H:%M:%S')] $1\" | tee -a \"$LOG_FILE\"\n}\n\nlog_message \"=== BẮT ĐẦU TIẾN TRÌNH SAO LƯU CHO DATABASE: ${DB_NAME} ===\"\n\n# Kiểm tra xem container có đang chạy hay không\nif ! docker ps --format '{{.Names}}' | grep -q \"^${CONTAINER_NAME}$\"; then\n    log_message \"LỖI: Container ${CONTAINER_NAME} không hoạt động hoặc không tồn tại!\"\n    exit 1\nfi\n\n# Thực hiện trích xuất dữ liệu và nén gzip\nif docker exec -t \"$CONTAINER_NAME\" pg_dump -U \"$DB_USER\" \"$DB_NAME\" | gzip > \"$FILENAME\"; then\n    FILE_SIZE=$(du -h \"$FILENAME\" | cut -f1)\n    log_message \"THÀNH CÔNG: Đã tạo bản sao lưu tại ${FILENAME} (Dung lượng: ${FILE_SIZE})\"\nelse\n    log_message \"LỖI: Tiến trình pg_dump thất bại!\"\n    rm -f \"$FILENAME\"\n    exit 1\nfi\n\n# Tự động dọn dẹp các file backup cũ quá số ngày quy định\nlog_message \"Đang dọn dẹp các bản backup cũ hơn ${RETENTION_DAYS} ngày...\"\nDELETED_COUNT=$(find \"$BACKUP_DIR\" -type f -name \"${DB_NAME}_*.sql.gz\" -mtime +${RETENTION_DAYS} -delete -print | wc -l)\nlog_message \"Đã xóa ${DELETED_COUNT} bản sao lưu cũ.\"\n\nlog_message \"=== HOÀN TẤT SAO LƯU THÀNH CÔNG ===\"\nexit 0\n",[207,407,408,414,419,425,431,436,443,455,460,466,478,489,500,511,531,557,568,582,587,596,633,639,644,657,662,668,711,725,734,740,745,751,804,836,855,861,869,884,891,896,901,907,920,982,995,1000,1008],{"__ignoreMap":232},[236,409,410],{"class":238,"line":239},[236,411,413],{"class":412},"sGGCZ","#!/bin/bash\n",[236,415,416],{"class":238,"line":367},[236,417,418],{"class":412},"# ==============================================================================\n",[236,420,422],{"class":238,"line":421},3,[236,423,424],{"class":412},"# SCRIPT TỰ ĐỘNG SAO LƯU POSTGRESQL TRONG DOCKER\n",[236,426,428],{"class":238,"line":427},4,[236,429,430],{"class":412},"# Tác giả: TechBlog Admin\n",[236,432,434],{"class":238,"line":433},5,[236,435,418],{"class":412},[236,437,439],{"class":238,"line":438},6,[236,440,442],{"emptyLinePlaceholder":441},true,"\n",[236,444,446,449,452],{"class":238,"line":445},7,[236,447,448],{"class":249},"set",[236,450,451],{"class":249}," -eo",[236,453,454],{"class":245}," pipefail\n",[236,456,458],{"class":238,"line":457},8,[236,459,442],{"emptyLinePlaceholder":441},[236,461,463],{"class":238,"line":462},9,[236,464,465],{"class":412},"# Cấu hình thông tin\n",[236,467,469,472,475],{"class":238,"line":468},10,[236,470,471],{"class":260},"CONTAINER_NAME",[236,473,474],{"class":253},"=",[236,476,477],{"class":245},"\"production_postgres\"\n",[236,479,481,484,486],{"class":238,"line":480},11,[236,482,483],{"class":260},"DB_USER",[236,485,474],{"class":253},[236,487,488],{"class":245},"\"pgadmin\"\n",[236,490,492,495,497],{"class":238,"line":491},12,[236,493,494],{"class":260},"DB_NAME",[236,496,474],{"class":253},[236,498,499],{"class":245},"\"core_production\"\n",[236,501,503,506,508],{"class":238,"line":502},13,[236,504,505],{"class":260},"BACKUP_DIR",[236,507,474],{"class":253},[236,509,510],{"class":245},"\"/var/backups/postgres\"\n",[236,512,514,517,519,522,525,528],{"class":238,"line":513},14,[236,515,516],{"class":260},"DATE_STAMP",[236,518,474],{"class":253},[236,520,521],{"class":260},"$(",[236,523,524],{"class":242},"date",[236,526,527],{"class":245}," +\"%Y%m%d_%H%M%S\"",[236,529,530],{"class":260},")\n",[236,532,534,537,539,542,544,547,549,552,554],{"class":238,"line":533},15,[236,535,536],{"class":260},"FILENAME",[236,538,474],{"class":253},[236,540,541],{"class":245},"\"${",[236,543,505],{"class":260},[236,545,546],{"class":245},"}/${",[236,548,494],{"class":260},[236,550,551],{"class":245},"}_${",[236,553,516],{"class":260},[236,555,556],{"class":245},"}.sql.gz\"\n",[236,558,560,563,565],{"class":238,"line":559},16,[236,561,562],{"class":260},"LOG_FILE",[236,564,474],{"class":253},[236,566,567],{"class":245},"\"/var/log/postgres_backup.log\"\n",[236,569,571,574,576,579],{"class":238,"line":570},17,[236,572,573],{"class":260},"RETENTION_DAYS",[236,575,474],{"class":253},[236,577,578],{"class":245},"7",[236,580,581],{"class":412}," # Lưu trữ tối đa trong 7 ngày\n",[236,583,585],{"class":238,"line":584},18,[236,586,442],{"emptyLinePlaceholder":441},[236,588,590,593],{"class":238,"line":589},19,[236,591,592],{"class":242},"log_message",[236,594,595],{"class":260},"() {\n",[236,597,599,602,605,607,610,613,616,618,621,624,627,630],{"class":238,"line":598},20,[236,600,601],{"class":249},"    echo",[236,603,604],{"class":245}," \"[$(",[236,606,524],{"class":242},[236,608,609],{"class":245}," '+%Y-%m-%d %H:%M:%S')] ",[236,611,612],{"class":249},"$1",[236,614,615],{"class":245},"\"",[236,617,292],{"class":253},[236,619,620],{"class":242}," tee",[236,622,623],{"class":249}," -a",[236,625,626],{"class":245}," \"",[236,628,629],{"class":260},"$LOG_FILE",[236,631,632],{"class":245},"\"\n",[236,634,636],{"class":238,"line":635},21,[236,637,638],{"class":260},"}\n",[236,640,642],{"class":238,"line":641},22,[236,643,442],{"emptyLinePlaceholder":441},[236,645,647,649,652,654],{"class":238,"line":646},23,[236,648,592],{"class":242},[236,650,651],{"class":245}," \"=== BẮT ĐẦU TIẾN TRÌNH SAO LƯU CHO DATABASE: ${",[236,653,494],{"class":260},[236,655,656],{"class":245},"} ===\"\n",[236,658,660],{"class":238,"line":659},24,[236,661,442],{"emptyLinePlaceholder":441},[236,663,665],{"class":238,"line":664},25,[236,666,667],{"class":412},"# Kiểm tra xem container có đang chạy hay không\n",[236,669,671,674,677,680,683,686,689,691,694,697,700,702,705,708],{"class":238,"line":670},26,[236,672,673],{"class":253},"if",[236,675,676],{"class":253}," !",[236,678,679],{"class":242}," docker",[236,681,682],{"class":245}," ps",[236,684,685],{"class":249}," --format",[236,687,688],{"class":245}," '{{.Names}}'",[236,690,292],{"class":253},[236,692,693],{"class":242}," grep",[236,695,696],{"class":249}," -q",[236,698,699],{"class":245}," \"^${",[236,701,471],{"class":260},[236,703,704],{"class":245},"}$\"",[236,706,707],{"class":260},"; ",[236,709,710],{"class":253},"then\n",[236,712,714,717,720,722],{"class":238,"line":713},27,[236,715,716],{"class":242},"    log_message",[236,718,719],{"class":245}," \"LỖI: Container ${",[236,721,471],{"class":260},[236,723,724],{"class":245},"} không hoạt động hoặc không tồn tại!\"\n",[236,726,728,731],{"class":238,"line":727},28,[236,729,730],{"class":249},"    exit",[236,732,733],{"class":249}," 1\n",[236,735,737],{"class":238,"line":736},29,[236,738,739],{"class":253},"fi\n",[236,741,743],{"class":238,"line":742},30,[236,744,442],{"emptyLinePlaceholder":441},[236,746,748],{"class":238,"line":747},31,[236,749,750],{"class":412},"# Thực hiện trích xuất dữ liệu và nén gzip\n",[236,752,754,756,758,760,762,764,767,769,771,773,775,778,780,782,785,787,789,791,793,795,798,800,802],{"class":238,"line":753},32,[236,755,673],{"class":253},[236,757,679],{"class":242},[236,759,246],{"class":245},[236,761,250],{"class":249},[236,763,626],{"class":245},[236,765,766],{"class":260},"$CONTAINER_NAME",[236,768,615],{"class":245},[236,770,267],{"class":245},[236,772,270],{"class":249},[236,774,626],{"class":245},[236,776,777],{"class":260},"$DB_USER",[236,779,615],{"class":245},[236,781,626],{"class":245},[236,783,784],{"class":260},"$DB_NAME",[236,786,615],{"class":245},[236,788,292],{"class":253},[236,790,295],{"class":242},[236,792,298],{"class":253},[236,794,626],{"class":245},[236,796,797],{"class":260},"$FILENAME",[236,799,615],{"class":245},[236,801,707],{"class":260},[236,803,710],{"class":253},[236,805,807,810,812,814,817,820,822,824,826,828,831,834],{"class":238,"line":806},33,[236,808,809],{"class":260},"    FILE_SIZE",[236,811,474],{"class":253},[236,813,521],{"class":260},[236,815,816],{"class":242},"du",[236,818,819],{"class":249}," -h",[236,821,626],{"class":245},[236,823,797],{"class":260},[236,825,615],{"class":245},[236,827,292],{"class":253},[236,829,830],{"class":242}," cut",[236,832,833],{"class":249}," -f1",[236,835,530],{"class":260},[236,837,839,841,844,846,849,852],{"class":238,"line":838},34,[236,840,716],{"class":242},[236,842,843],{"class":245}," \"THÀNH CÔNG: Đã tạo bản sao lưu tại ${",[236,845,536],{"class":260},[236,847,848],{"class":245},"} (Dung lượng: ${",[236,850,851],{"class":260},"FILE_SIZE",[236,853,854],{"class":245},"})\"\n",[236,856,858],{"class":238,"line":857},35,[236,859,860],{"class":253},"else\n",[236,862,864,866],{"class":238,"line":863},36,[236,865,716],{"class":242},[236,867,868],{"class":245}," \"LỖI: Tiến trình pg_dump thất bại!\"\n",[236,870,872,875,878,880,882],{"class":238,"line":871},37,[236,873,874],{"class":242},"    rm",[236,876,877],{"class":249}," -f",[236,879,626],{"class":245},[236,881,797],{"class":260},[236,883,632],{"class":245},[236,885,887,889],{"class":238,"line":886},38,[236,888,730],{"class":249},[236,890,733],{"class":249},[236,892,894],{"class":238,"line":893},39,[236,895,739],{"class":253},[236,897,899],{"class":238,"line":898},40,[236,900,442],{"emptyLinePlaceholder":441},[236,902,904],{"class":238,"line":903},41,[236,905,906],{"class":412},"# Tự động dọn dẹp các file backup cũ quá số ngày quy định\n",[236,908,910,912,915,917],{"class":238,"line":909},42,[236,911,592],{"class":242},[236,913,914],{"class":245}," \"Đang dọn dẹp các bản backup cũ hơn ${",[236,916,573],{"class":260},[236,918,919],{"class":245},"} ngày...\"\n",[236,921,923,926,928,930,933,935,938,940,943,946,949,952,954,957,960,963,966,969,972,974,977,980],{"class":238,"line":922},43,[236,924,925],{"class":260},"DELETED_COUNT",[236,927,474],{"class":253},[236,929,521],{"class":260},[236,931,932],{"class":242},"find",[236,934,626],{"class":245},[236,936,937],{"class":260},"$BACKUP_DIR",[236,939,615],{"class":245},[236,941,942],{"class":249}," -type",[236,944,945],{"class":245}," f",[236,947,948],{"class":249}," -name",[236,950,951],{"class":245}," \"${",[236,953,494],{"class":260},[236,955,956],{"class":245},"}_*.sql.gz\"",[236,958,959],{"class":249}," -mtime",[236,961,962],{"class":245}," +",[236,964,965],{"class":260},"${RETENTION_DAYS} ",[236,967,968],{"class":249},"-delete",[236,970,971],{"class":249}," -print",[236,973,292],{"class":253},[236,975,976],{"class":242}," wc",[236,978,979],{"class":249}," -l",[236,981,530],{"class":260},[236,983,985,987,990,992],{"class":238,"line":984},44,[236,986,592],{"class":242},[236,988,989],{"class":245}," \"Đã xóa ${",[236,991,925],{"class":260},[236,993,994],{"class":245},"} bản sao lưu cũ.\"\n",[236,996,998],{"class":238,"line":997},45,[236,999,442],{"emptyLinePlaceholder":441},[236,1001,1003,1005],{"class":238,"line":1002},46,[236,1004,592],{"class":242},[236,1006,1007],{"class":245}," \"=== HOÀN TẤT SAO LƯU THÀNH CÔNG ===\"\n",[236,1009,1011,1014],{"class":238,"line":1010},47,[236,1012,1013],{"class":249},"exit",[236,1015,1016],{"class":249}," 0\n",[171,1018,1019,1020,1023],{},"Phân quyền thực thi nghiêm ngặt (chỉ cho phép user ",[207,1021,1022],{},"root"," được đọc và chạy script):",[227,1025,1027],{"className":229,"code":1026,"language":231,"meta":232,"style":232},"sudo chmod 700 /opt/scripts/backup_postgres.sh\n",[207,1028,1029],{"__ignoreMap":232},[236,1030,1031,1033,1035,1037],{"class":238,"line":239},[236,1032,352],{"class":242},[236,1034,372],{"class":245},[236,1036,375],{"class":249},[236,1038,399],{"class":245},[200,1040],{},[166,1042,1044],{"id":1043},"_3-chạy-thử-nghiệm-script-thủ-công","3. Chạy thử nghiệm Script thủ công",[171,1046,1047],{},"Hãy kiểm tra chạy thử script lần đầu để đảm bảo không có lỗi phân quyền hay sai tên container:",[227,1049,1051],{"className":229,"code":1050,"language":231,"meta":232,"style":232},"sudo /opt/scripts/backup_postgres.sh\n",[207,1052,1053],{"__ignoreMap":232},[236,1054,1055,1057],{"class":238,"line":239},[236,1056,352],{"class":242},[236,1058,399],{"class":245},[171,1060,1061],{},"Kiểm tra file sao lưu đã được tạo trong thư mục backup:",[227,1063,1065],{"className":229,"code":1064,"language":231,"meta":232,"style":232},"ls -lh /var/backups/postgres/\n",[207,1066,1067],{"__ignoreMap":232},[236,1068,1069,1072,1075],{"class":238,"line":239},[236,1070,1071],{"class":242},"ls",[236,1073,1074],{"class":249}," -lh",[236,1076,1077],{"class":245}," /var/backups/postgres/\n",[171,1079,1080],{},"Kiểm tra nội dung log:",[227,1082,1084],{"className":229,"code":1083,"language":231,"meta":232,"style":232},"cat /var/log/postgres_backup.log\n",[207,1085,1086],{"__ignoreMap":232},[236,1087,1088,1091],{"class":238,"line":239},[236,1089,1090],{"class":242},"cat",[236,1092,1093],{"class":245}," /var/log/postgres_backup.log\n",[200,1095],{},[166,1097,1099],{"id":1098},"_4-thiết-lập-lịch-chạy-tự-động-với-cron-job","4. Thiết lập Lịch chạy tự động với Cron Job",[171,1101,1102,1103,1106],{},"Để máy chủ tự động thực hiện sao lưu vào ",[178,1104,1105],{},"02:00 sáng mỗi ngày"," (thời điểm lượng truy cập hệ thống thấp nhất):",[171,1108,1109,1110,384],{},"Mở bảng lập lịch Cron của tài khoản ",[207,1111,1022],{},[227,1113,1115],{"className":229,"code":1114,"language":231,"meta":232,"style":232},"sudo crontab -e\n",[207,1116,1117],{"__ignoreMap":232},[236,1118,1119,1121,1124],{"class":238,"line":239},[236,1120,352],{"class":242},[236,1122,1123],{"class":245}," crontab",[236,1125,1126],{"class":249}," -e\n",[171,1128,1129],{},"Thêm dòng sau vào cuối file crontab:",[227,1131,1135],{"className":1132,"code":1133,"language":1134,"meta":232,"style":232},"language-cron shiki shiki-themes github-dark github-dark github-dark","# Chạy sao lưu PostgreSQL vào lúc 02:00 AM hàng ngày\n0 2 * * * /opt/scripts/backup_postgres.sh > /dev/null 2>&1\n","cron",[207,1136,1137,1142],{"__ignoreMap":232},[236,1138,1139],{"class":238,"line":239},[236,1140,1141],{},"# Chạy sao lưu PostgreSQL vào lúc 02:00 AM hàng ngày\n",[236,1143,1144],{"class":238,"line":367},[236,1145,1146],{},"0 2 * * * /opt/scripts/backup_postgres.sh > /dev/null 2>&1\n",[171,1148,1149,1150,1153,1154,1153,1157,1160],{},"Lưu và đóng file (",[207,1151,1152],{},"Ctrl + O",", ",[207,1155,1156],{},"Enter",[207,1158,1159],{},"Ctrl + X"," trong nano).",[171,1162,1163],{},"Kiểm tra danh sách cron job đang hoạt động:",[227,1165,1167],{"className":229,"code":1166,"language":231,"meta":232,"style":232},"sudo crontab -l\n",[207,1168,1169],{"__ignoreMap":232},[236,1170,1171,1173,1175],{"class":238,"line":239},[236,1172,352],{"class":242},[236,1174,1123],{"class":245},[236,1176,1177],{"class":249}," -l\n",[200,1179],{},[166,1181,1183],{"id":1182},"_5-qui-trình-kiểm-thử-phục-hồi-dữ-liệu-database-restore","5. Qui trình kiểm thử phục hồi dữ liệu (Database Restore)",[171,1185,1186],{},"Đừng đợi đến khi xảy ra thảm họa mới tìm cách phục hồi. Hãy thực hành quy trình khôi phục định kỳ theo các bước sau:",[1188,1189,1191],"h3",{"id":1190},"bước-51-giải-nén-và-nạp-dữ-liệu-vào-container","Bước 5.1: Giải nén và nạp dữ liệu vào container",[171,1193,1194,1195,384],{},"Giả sử bạn cần khôi phục file ",[207,1196,1197],{},"/var/backups/postgres/core_production_20241020_020000.sql.gz",[227,1199,1201],{"className":229,"code":1200,"language":231,"meta":232,"style":232},"# Giải nén và nạp trực tiếp qua lệnh psql trong Docker\ngunzip -c /var/backups/postgres/core_production_20241020_020000.sql.gz | docker exec -i production_postgres psql -U pgadmin -d core_production\n",[207,1202,1203,1208],{"__ignoreMap":232},[236,1204,1205],{"class":238,"line":239},[236,1206,1207],{"class":412},"# Giải nén và nạp trực tiếp qua lệnh psql trong Docker\n",[236,1209,1210,1213,1216,1219,1221,1223,1225,1228,1231,1234,1236,1239,1242],{"class":238,"line":367},[236,1211,1212],{"class":242},"gunzip",[236,1214,1215],{"class":249}," -c",[236,1217,1218],{"class":245}," /var/backups/postgres/core_production_20241020_020000.sql.gz",[236,1220,292],{"class":253},[236,1222,679],{"class":242},[236,1224,246],{"class":245},[236,1226,1227],{"class":249}," -i",[236,1229,1230],{"class":245}," production_postgres",[236,1232,1233],{"class":245}," psql",[236,1235,270],{"class":249},[236,1237,1238],{"class":245}," pgadmin",[236,1240,1241],{"class":249}," -d",[236,1243,1244],{"class":245}," core_production\n",[171,1246,1247,1248,1251],{},"Trong môi trường thử nghiệm khôi phục, bạn nên tạo một cơ sở dữ liệu tạm thời (ví dụ: ",[207,1249,1250],{},"core_restore_test",") để kiểm tra tính toàn vẹn của dữ liệu trước khi đè lên cơ sở dữ liệu chính:",[227,1253,1255],{"className":229,"code":1254,"language":231,"meta":232,"style":232},"# 1. Tạo database test\ndocker exec -it production_postgres psql -U pgadmin -c \"CREATE DATABASE core_restore_test;\"\n \n# 2. Nạp dữ liệu vào database test\ngunzip -c /var/backups/postgres/core_production_20241020_020000.sql.gz | docker exec -i production_postgres psql -U pgadmin -d core_restore_test\n \n# 3. Xóa database test sau khi kiểm tra xong\ndocker exec -it production_postgres psql -U pgadmin -c \"DROP DATABASE core_restore_test;\"\n",[207,1256,1257,1262,1284,1289,1294,1323,1327,1332],{"__ignoreMap":232},[236,1258,1259],{"class":238,"line":239},[236,1260,1261],{"class":412},"# 1. Tạo database test\n",[236,1263,1264,1266,1268,1271,1273,1275,1277,1279,1281],{"class":238,"line":367},[236,1265,25],{"class":242},[236,1267,246],{"class":245},[236,1269,1270],{"class":249}," -it",[236,1272,1230],{"class":245},[236,1274,1233],{"class":245},[236,1276,270],{"class":249},[236,1278,1238],{"class":245},[236,1280,1215],{"class":249},[236,1282,1283],{"class":245}," \"CREATE DATABASE core_restore_test;\"\n",[236,1285,1286],{"class":238,"line":421},[236,1287,1288],{"class":260}," \n",[236,1290,1291],{"class":238,"line":427},[236,1292,1293],{"class":412},"# 2. Nạp dữ liệu vào database test\n",[236,1295,1296,1298,1300,1302,1304,1306,1308,1310,1312,1314,1316,1318,1320],{"class":238,"line":433},[236,1297,1212],{"class":242},[236,1299,1215],{"class":249},[236,1301,1218],{"class":245},[236,1303,292],{"class":253},[236,1305,679],{"class":242},[236,1307,246],{"class":245},[236,1309,1227],{"class":249},[236,1311,1230],{"class":245},[236,1313,1233],{"class":245},[236,1315,270],{"class":249},[236,1317,1238],{"class":245},[236,1319,1241],{"class":249},[236,1321,1322],{"class":245}," core_restore_test\n",[236,1324,1325],{"class":238,"line":438},[236,1326,1288],{"class":260},[236,1328,1329],{"class":238,"line":445},[236,1330,1331],{"class":412},"# 3. Xóa database test sau khi kiểm tra xong\n",[236,1333,1334,1336,1338,1340,1342,1344,1346,1348,1350],{"class":238,"line":457},[236,1335,25],{"class":242},[236,1337,246],{"class":245},[236,1339,1270],{"class":249},[236,1341,1230],{"class":245},[236,1343,1233],{"class":245},[236,1345,270],{"class":249},[236,1347,1238],{"class":245},[236,1349,1215],{"class":249},[236,1351,1352],{"class":245}," \"DROP DATABASE core_restore_test;\"\n",[200,1354],{},[166,1356,1358],{"id":1357},"_6-chiến-lược-mở-rộng-sao-lưu-offsite-lên-cloud-storage-s3-r2","6. Chiến lược mở rộng: Sao lưu Offsite lên Cloud Storage (S3 / R2)",[171,1360,1361],{},"Lưu trữ bản backup trên cùng một máy chủ VPS vẫn tiềm ẩn rủi ro nếu toàn bộ ổ cứng máy chủ bị hỏng vật lý hoặc nhà cung cấp VPS gặp sự cố trung tâm dữ liệu.",[171,1363,1364,1365,1368,1369,1372,1373,1368,1376,384],{},"Bạn nên mở rộng script trên bằng cách cài đặt công cụ ",[178,1366,1367],{},"AWS CLI"," hoặc ",[178,1370,1371],{},"rclone"," để tự động đẩy file backup lên các dịch vụ lưu trữ đám mây giá rẻ như ",[178,1374,1375],{},"Cloudflare R2",[178,1377,1378],{},"AWS S3 Glacier",[227,1380,1382],{"className":229,"code":1381,"language":231,"meta":232,"style":232},"# Ví dụ đẩy file lên S3 / R2 bucket\naws s3 cp \"$FILENAME\" s3://my-company-backups/postgres/ --endpoint-url https://\u003CACCOUNT_ID>.r2.cloudflarestorage.com\n",[207,1383,1384,1389],{"__ignoreMap":232},[236,1385,1386],{"class":238,"line":239},[236,1387,1388],{"class":412},"# Ví dụ đẩy file lên S3 / R2 bucket\n",[236,1390,1391,1394,1397,1400,1402,1404,1406,1409,1412,1415,1418,1421,1424,1426],{"class":238,"line":367},[236,1392,1393],{"class":242},"aws",[236,1395,1396],{"class":245}," s3",[236,1398,1399],{"class":245}," cp",[236,1401,626],{"class":245},[236,1403,797],{"class":260},[236,1405,615],{"class":245},[236,1407,1408],{"class":245}," s3://my-company-backups/postgres/",[236,1410,1411],{"class":249}," --endpoint-url",[236,1413,1414],{"class":245}," https://",[236,1416,1417],{"class":253},"\u003C",[236,1419,1420],{"class":245},"ACCOUNT_I",[236,1422,1423],{"class":260},"D",[236,1425,264],{"class":253},[236,1427,1428],{"class":245},".r2.cloudflarestorage.com\n",[200,1430],{},[166,1432,1434],{"id":1433},"bảng-so-sánh-các-phương-pháp-backup-postgresql","Bảng so sánh các phương pháp Backup PostgreSQL",[1436,1437,1438,1458],"table",{},[1439,1440,1441],"thead",{},[1442,1443,1444,1449,1452,1455],"tr",{},[1445,1446,1448],"th",{"align":1447},"left","Phương pháp",[1445,1450,1451],{"align":1447},"Ưu điểm",[1445,1453,1454],{"align":1447},"Nhược điểm",[1445,1456,1457],{"align":1447},"Phù hợp nhất",[1459,1460,1461,1480,1499],"tbody",{},[1442,1462,1463,1471,1474,1477],{},[1464,1465,1466],"td",{"align":1447},[178,1467,1468,1470],{},[207,1469,213],{}," (Logical)",[1464,1472,1473],{"align":1447},"File SQL dạng text, dễ đọc, khôi phục được giữa các phiên bản PostgreSQL khác nhau",[1464,1475,1476],{"align":1447},"Tốc độ chậm với database dung lượng cực lớn (>100GB)",[1464,1478,1479],{"align":1447},"Hầu hết các website và ứng dụng vừa & nhỏ (\u003C50GB)",[1442,1481,1482,1490,1493,1496],{},[1464,1483,1484],{"align":1447},[178,1485,1486,1489],{},[207,1487,1488],{},"pg_basebackup"," (Physical)",[1464,1491,1492],{"align":1447},"Sao chép nguyên khối nhị phân, tốc độ cực nhanh",[1464,1494,1495],{"align":1447},"Yêu cầu cùng kiến trúc và phiên bản PostgreSQL chính xác",[1464,1497,1498],{"align":1447},"Hệ thống lớn hàng trăm GB, thiết lập Streaming Replication",[1442,1500,1501,1506,1509,1512],{},[1464,1502,1503],{"align":1447},[178,1504,1505],{},"Volume Snapshot",[1464,1507,1508],{"align":1447},"Snapshot tức thời ở mức ổ đĩa VPS",[1464,1510,1511],{"align":1447},"Phải lock IO để đảm bảo tính nhất quán (Crash-consistent)",[1464,1513,1514],{"align":1447},"Sao lưu hạ tầng toàn diện",[200,1516],{},[166,1518,1520],{"id":1519},"tổng-kết","Tổng kết",[171,1522,1523,1524,1527],{},"Bằng cách kết hợp script bash tối ưu, nén gzip và Cron Job tự động, bạn đã hoàn thiện một lá chắn bảo vệ an toàn cho cơ sở dữ liệu của mình. Hãy nhớ kiểm tra log ",[207,1525,1526],{},"/var/log/postgres_backup.log"," định kỳ để đảm bảo các bản sao lưu luôn được tạo ra đều đặn mỗi đêm.",[1529,1530,1531],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sb7EE, html code.shiki .sb7EE{--shiki-default:#B392F0;--shiki-dark:#B392F0;--shiki-light:#B392F0}html pre.shiki code .skqr8, html code.shiki .skqr8{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-light:#9ECBFF}html pre.shiki code .sKJT9, html code.shiki .sKJT9{--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-light:#79B8FF}html pre.shiki code .sWuGj, html code.shiki .sWuGj{--shiki-default:#F97583;--shiki-dark:#F97583;--shiki-light:#F97583}html pre.shiki code .sFJ4l, html code.shiki .sFJ4l{--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8;--shiki-light:#E1E4E8}html pre.shiki code .sGGCZ, html code.shiki .sGGCZ{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-light:#6A737D}",{"title":232,"searchDepth":367,"depth":367,"links":1533},[1534,1535,1537,1539,1540,1541,1544,1545,1546],{"id":168,"depth":367,"text":169},{"id":204,"depth":367,"text":1536},"1. Nguyên lí hoạt động của docker exec và pg_dump",{"id":334,"depth":367,"text":1538},"2. Viết Script Sao lưu tự động chuyên nghiệp (backup_postgres.sh)",{"id":1043,"depth":367,"text":1044},{"id":1098,"depth":367,"text":1099},{"id":1182,"depth":367,"text":1183,"children":1542},[1543],{"id":1190,"depth":421,"text":1191},{"id":1357,"depth":367,"text":1358},{"id":1433,"depth":367,"text":1434},{"id":1519,"depth":367,"text":1520},[25,26],false,"md",{"src":33,"alt":34},{},{"title":22,"description":23},"Tự học Docker từ A-Z","backup-postgres-docker","posts/backup-postgres-docker",[28,29,30,10],"2026-08-26","10WCeLcjGv",[1560,1565,1569,1574,1579,1584,1589,1594,1599,1604,1609,1614],{"path":5,"title":6,"categories":1561,"tags":1562,"date":16,"draft":1548,"slug":1563,"description":7,"image":1564},[9,10],[12,13,14,15],"incident-checklist",{"src":18,"alt":19},{"path":21,"title":22,"categories":1566,"tags":1567,"date":31,"draft":1548,"slug":1554,"description":23,"image":1568},[25,26],[28,29,30,10],{"src":33,"alt":34},{"path":36,"title":37,"categories":1570,"tags":1571,"date":44,"draft":1548,"slug":1572,"description":38,"image":1573},[25,10],[41,42,43],"docker-compose-production",{"src":46,"alt":47},{"path":49,"title":50,"categories":1575,"tags":1576,"date":58,"draft":1548,"slug":1577,"description":51,"image":1578},[9,10],[54,55,56,57],"monitoring-server-basics",{"src":60,"alt":61},{"path":63,"title":64,"categories":1580,"tags":1581,"date":71,"draft":1548,"slug":1582,"description":65,"image":1583},[9,67],[10,69,70],"nginx-reverse-proxy",{"src":73,"alt":74},{"path":76,"title":77,"categories":1585,"tags":1586,"date":83,"draft":1548,"slug":1587,"description":78,"image":1588},[9,14],[81,82,10],"how-to-secure-a-vps",{"src":85,"alt":86},{"path":88,"title":89,"categories":1590,"tags":1591,"date":95,"draft":1548,"slug":1592,"description":90,"image":1593},[9,10],[93,94,43,41],"systemd-node-service",{"src":97,"alt":98},{"path":100,"title":101,"categories":1595,"tags":1596,"date":107,"draft":1548,"slug":1597,"description":102,"image":1598},[9,25],[105,10,106],"how-to-install-docker-on-ubuntu-server",{"src":109,"alt":110},{"path":112,"title":113,"categories":1600,"tags":1601,"date":118,"draft":1548,"slug":1602,"description":114,"image":1603},[9,14],[117,10,15],"ssh-key-authentication",{"src":120,"alt":121},{"path":123,"title":124,"categories":1605,"tags":1606,"date":131,"draft":1548,"slug":1607,"description":125,"image":1608},[9,14],[128,129,130,15],"ufw-firewall-basics",{"src":133,"alt":134},{"path":136,"title":137,"categories":1610,"tags":1611,"date":145,"draft":1548,"slug":1612,"description":138,"image":1613},[140,10],[142,143,144,30],"git-deploy-key",{"src":147,"alt":148},{"path":150,"title":151,"categories":1615,"tags":1616,"date":155,"draft":1548,"slug":1617,"description":152,"image":1618},[9],[106,105,15],"ubuntu-server-initial-setup",{"src":157,"alt":158},[1620,1621,1622],{"path":100,"title":101,"series":1553,"series_order":239,"date":107,"draft":1548,"slug":1597},{"path":36,"title":37,"series":1553,"series_order":367,"date":44,"draft":1548,"slug":1572},{"path":21,"title":22,"series":1553,"series_order":421,"date":31,"draft":1548,"slug":1554},1789616168113]