Cách cài đặt và cấu hình Drone trên Ubuntu 16.04
Cảnh báo : Phiên bản Drone này không được dùng nữa. Để được trợ giúp cài đặt version Drone mới nhất, hãy truy cập hướng dẫn cài đặt Drone Ubuntu 20.04 của ta .Drone là một nền tảng phân phối và tích hợp liên tục phổ biến được tích hợp sẵn trong Go. Nó tích hợp với nhiều dịch vụ repository kiểm soát version phổ biến như GitHub, GitLab và Bitbucket để theo dõi các thay đổi mã và tự động xây dựng và kiểm tra các thay đổi khi chúng được commit .
Trong hướng dẫn này, ta sẽ trình bày cách cài đặt môi trường tích hợp liên tục Drone hoàn chỉnh cho cơ sở hạ tầng của bạn. Ta sẽ cài đặt Drone và cấu hình nó để tích hợp với kho mã nguồn của bạn. Trên đường đi, ta sẽ cấu hình Nginx, được bảo vệ bởi Let's Encrypt, làm giao diện user cho Drone. Điều này sẽ mã hóa các yêu cầu đến giao diện web của Drone và cho phép server CI tích hợp an toàn với server mã nguồn.
Yêu cầu
Để bắt đầu, bạn nên cấu hình server Ubuntu 16.04 với user sudo
không phải root cho các việc quản trị. Server cũng phải có firewall để lọc các kết nối đến. Bạn có thể tìm hiểu cách cấu hình các mục này theo hướng dẫn cài đặt server ban đầu Ubuntu 16.04 .
Bạn sẽ phải hoàn thành một số bước bổ sung để đáp ứng các yêu cầu khác cho cài đặt của ta . Vì Drone chủ yếu được phân phối dưới dạng Docker image , ta sẽ sử dụng Docker Compose để quản lý các containers server CI. Vì mục đích bảo mật và hiệu suất, ta sẽ gửi yêu cầu ủy quyền tới Drone thông qua một version Nginx được bảo vệ bởi Let's Encrypt. Bạn cần một domain gắn với server CI của bạn để cài đặt đúng cách.
Trước khi bạn bắt đầu, hãy sử dụng các bài viết sau để cài đặt các yêu cầu bổ sung sau:
- Cách cài đặt và sử dụng Docker trên Ubuntu 16.04
- Cách cài đặt Docker Compose trên Ubuntu 16.04 : Cài đặt Docker và Docker Compose theo các yêu cầu và bước đầu tiên của hướng dẫn này.
- Cách cài đặt Nginx trên Ubuntu 16.04 : Cài đặt Nginx trên server .
- Cách bảo mật Nginx bằng Let's Encrypt trên Ubuntu 16.04 : Bảo mật Nginx bằng certificate SSL tin cậy .
Khi bạn hoàn thành các hướng dẫn trên, server Drone của bạn sẽ có:
- User
sudo
cấu hình cho các việc quản trị - Đã bật firewall UFW. Nó sẽ chặn tất cả các kết nối ngoại trừ các yêu cầu SSH, HTTP và HTTPS trên các cổng 22, 80 và 443 tương ứng.
- Docker và Docker Compose đã được cài đặt.
- Server Nginx được cấu hình bằng certificate SSL do Let's Encrypt cung cấp
Tiếp tục bên dưới khi đã sẵn sàng bắt đầu.
Thêm ứng dụng vào repository mã nguồn của bạn
Để theo dõi các thay đổi mã nhằm kích hoạt các giai đoạn xây dựng và thử nghiệm, Drone cần quyền truy cập vào kho mã nguồn của bạn. Drone có thể tích hợp với GitHub , GitLab , Gogs , Bitbucket Cloud và Bitbucket Server .
Trong hướng dẫn này, ta sẽ tập trung vào việc tích hợp với repository GitHub, nhưng quá trình này phải tương tự đối với các hệ thống khác. Nếu bạn đang sử dụng một repository mã nguồn khác, hãy nhấp vào liên kết thích hợp ở trên để tìm hiểu về cấu hình phần mềm cụ thể mà bạn cần .
Bắt đầu bằng cách truy cập account GitHub của bạn. Nhấp vào biểu tượng user của bạn ở góc trên bên phải và chọn Cài đặt từ menu thả xuống:
Tiếp theo, tìm mục Ứng dụng OAuth trong phần Cài đặt dành cho nhà phát triển ở bên trái màn hình:
Trên trang sau đó, nhấp vào Đăng ký ứng dụng mới :
Tiếp theo, bạn sẽ thấy biểu mẫu đăng ký ứng dụng OAuth:
Bạn cần điền vào các trường sau (các trường này có trên GitHub. Các nhà cung cấp dịch vụ lưu trữ khác có thể có các dấu nhắc khác nhau):
- Tên ứng dụng : Tên bạn chọn để xác định tích hợp. “Drone” là một lựa chọn tốt nếu bạn không có nhu cầu đặc biệt.
- URL trang chủ : Tên domain của server Drone của bạn. Sử dụng
https://
tại đây vì ta đang sử dụng domain được bảo mật. - Mô tả ứng dụng : Mô tả đơn giản về Drone và mục đích của nó.
- URL gọi lại ủy quyền : Đây phải là công cụ chỉ định giản đồ
https://
, theo sau là domain của server Drone của bạn, theo sau là/authorize
. Nếu domain của ta làexample.com
, thì file này sẽ làhttps:// example.com /authorize
.
Khi đã sẵn sàng , hãy nhấp vào Đăng ký ứng dụng .
Trên trang sau, bạn sẽ thấy thông tin chi tiết về ứng dụng mới của bạn . Hai mục ta cần là ID khách hàng và Bí mật khách hàng :
Sao chép hai giá trị này để sử dụng sau. Ta cần những thứ này để kết nối Drone với account GitHub của ta .
Kéo hình ảnh Drone Docker và chuẩn bị cấu hình
Đến đây bạn đã đăng ký server Drone của bạn với nhà cung cấp repository , bạn có thể cài đặt và cấu hình Drone trên server của bạn .
Drone được phân phối dưới dạng containers Docker, vì vậy nó sẽ được tự động download nếu ta sử dụng nó trong file Docker Compose. Tuy nhiên, để tăng tốc quá trình một chút, ta có thể kéo hình ảnh xuống trước:
- docker pull drone/drone:0.7
Hình ảnh Drone Docker là một containers thống nhất có thể chạy theo một số cách khác nhau. Ta sẽ chạy một containers hoạt động như server Drone, điều phối quyền truy cập repository , lưu trữ giao diện user web và cung cấp API. Sử dụng cùng một hình ảnh với các cài đặt khác nhau, ta sẽ chạy một containers khác với quyền là tác nhân Drone, chịu trách nhiệm xây dựng và thử nghiệm phần mềm từ các kho được cấu hình .
Ta sẽ chạy cả hai containers này trên server Drone bằng Docker Compose. Bắt đầu bằng cách tạo một folder cấu hình để lưu trữ các file ta cần:
- sudo mkdir /etc/drone
Tiếp theo, ta sẽ tạo một vài file bên trong để cấu hình các dịch vụ của ta .
Tạo file docker composer cho Drone
Đầu tiên, tạo file Docker Compose trong folder cấu hình:
- sudo nano /etc/drone/docker-compose.yml
Bên trong, ta sẽ đánh dấu định dạng file Docker Compose là version “3”. Sau đó, ta sẽ xác định các dịch vụ cho cả hai dịch vụ mà ta đã mô tả ở trên.
Dịch vụ drone-server
sẽ bắt đầu lắng nghe containers server Drone chính trên cổng 8000. Ta sẽ gắn folder /var/lib/drone
bên trong containers để Drone có thể duy trì dữ liệu của nó. Ta sẽ cấu hình dịch vụ để khởi động lại tự động và đọc hướng dẫn cấu hình chi tiết hơn dưới dạng các biến môi trường được xác định trong file mà ta sẽ tạo tại /etc/drone/server.env
.
Dịch vụ drone-agent
sử dụng cùng một hình ảnh, bắt đầu bằng lệnh agent
. Nó nhận được hướng dẫn từ version server Drone chính, vì vậy mặc dù nó không cần quyền truy cập mạng chung nhưng nó cần được khởi động sau dịch vụ Drone. Nó cũng cần quyền truy cập vào file socket của Docker để quay các containers nhằm chạy các bước xây dựng và thử nghiệm thực tế. Giống như dịch vụ drone-server
, dịch vụ này cũng sẽ tự động khởi động lại và đọc file môi trường tại /etc/drone/agent.env
để có cấu hình bổ sung.
Sử dụng file Docker Compose sau đây để cấu hình hai dịch vụ này. Hãy chú ý đến định dạng YAML của file , vì lỗi trong thụt lề hoặc định dạng có thể gây ra lỗi:
version: '3' services: drone-server: image: drone/drone:0.7 ports: - 127.0.0.1:8000:8000 volumes: - /var/lib/drone:/var/lib/drone restart: always env_file: - /etc/drone/server.env drone-agent: image: drone/drone:0.7 command: agent depends_on: - drone-server volumes: - /var/run/docker.sock:/var/run/docker.sock restart: always env_file: - /etc/drone/agent.env
Khi bạn hoàn tất, hãy lưu file Docker Compose.
Cấu hình file biến môi trường của server Drone
Tiếp theo, ta cần tạo file biến môi trường của server Drone mà ta đã tham chiếu trong file Docker Compose ở trên.
Trước khi mở file , ta nên tạo một khóa mạnh để xác thực các thành phần tác nhân và server . Mặc dù cài đặt của ta sẽ có cả hai thành phần này trên cùng một server , khi cơ sở hạ tầng thử nghiệm của bạn mở rộng, một khóa mạnh là điều cần thiết. Trên dòng lệnh, tạo khóa bằng lệnh :
- LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 65 && echo
Lệnh này tạm thời đặt ngôn ngữ trong shell thành một phạm vi ký tự hạn chế. Sau đó, nó lấy một stream byte ngẫu nhiên từ /dev/urandom
và lọc thêm bất kỳ ký tự không phải chữ và số nào. Ta lấy 65 ký tự đầu tiên làm key của ta .
Đầu ra sẽ giống như sau ( Không sao chép giá trị bên dưới! Hãy tạo giá trị của bạn ! ):
OutputERmA7xubDvTa8i0wYBlljc9yjT1NJPG7xOlZBwAdMAmBYL4RZE4QngxWcCLowk9KN
Sao chép khóa đã tạo để sử dụng trong file môi trường server .
Tạo một file mới tại /etc/drone/server.env
và mở nó trong editor của bạn:
- sudo nano /etc/drone/server.env
Bên trong, ta sẽ xác định các biến môi trường mà Drone sử dụng để kết nối để liên kết bắt đầu dịch vụ, kết nối với nhà cung cấp repository và đặt policy cấp quyền account . Bạn cần các giá trị mà bạn đã sao chép từ nhà cung cấp repository của bạn trước đó để điền các giá trị một cách chính xác.
Để bắt đầu, cài đặt các DRONE_HOST
và DRONE_SECRET
giá trị. Đặt DRONE_SECRET
thành khóa bạn đã tạo trên dòng lệnh. Cài đặt DRONE_HOST
thông báo cho Drone về địa chỉ có thể truy cập của nó. Đây phải là domain được bảo vệ Let's Encrypt của bạn, đứng trước trình chỉ định schemas https://
:
# Service settings DRONE_SECRET=secret_generated_on_command_line DRONE_HOST=https://example.com
Tiếp theo, ta sẽ cấu hình tích hợp với nhà cung cấp VCS của ta , trong trường hợp của ta là GitHub. Các cài đặt thích hợp cho dự án của bạn có thể khác nhau tùy thuộc vào nhu cầu của bạn và cách tổ chức nội dung GitHub của bạn.
Ta sẽ khóa cài đặt Drone của bạn và vô hiệu hóa đăng ký đang mở bằng cách đặt DRONE_OPEN
thành false
. Điều này nghĩa là chỉ những tên account GitHub được chỉ định trong DRONE_ADMIN
mới có thể đăng nhập.
Lưu ý : Nếu bạn làm việc với cộng tác viên với quyền là một tổ chức GitHub, tốt hơn nên đặt DRONE_OPEN
thành true
và thay DRONE_ADMIN
bằng DRONE_ORGS
. Cài đặt DRONE_ORGS
cho phép bạn chỉ định một hoặc nhiều tổ chức GitHub có các thành viên được phép đăng ký. Drone sẽ giới hạn đăng ký cho những user thuộc các group đó.
Đảm bảo rằng DRONE_ADMIN
chứa tên account GitHub của bạn.
Sau đó, kích hoạt plugin tích hợp GitHub bằng cách đặt DRONE_GITHUB
thành true
. Sau đó, ta sẽ đặt DRONE_GITHUB_CLIENT
và DRONE_GITHUB_SECRET
thành các khóa mà ta đã sao chép từ trang ứng dụng GitHub OAuth khi ta đăng ký ứng dụng Drone:
# Service settings DRONE_SECRET=secret_generated_on_command_line DRONE_HOST=https://example.com # Registration settings DRONE_OPEN=false DRONE_ADMIN=sammytheshark # GitHub Settings DRONE_GITHUB=true DRONE_GITHUB_CLIENT=Client_ID_from_GitHub DRONE_GITHUB_SECRET=Client_Secret_from_GitHub
Ta đã hoàn tất cấu hình thành phần server . Trước khi rời đi, hãy sao chép giá trị DRONE_SECRET
từ file . Ta cần đặt cùng một khóa này trong phần tiếp theo khi ta cấu hình tác nhân. Lưu file khi bạn hoàn tất.
Cấu hình file biến môi trường của tác nhân bay không người lái
Tiếp theo, ta sẽ tạo một file môi trường cho thành phần tác nhân Drone.
Mở một file mới để đặt các biến môi trường tác nhân:
- sudo nano /etc/drone/agent.env
Bên trong, ta chỉ cần xác định hai giá trị. DRONE_SECRET
sẽ trùng với cấu hình trong file sever.env
.
Cài đặt DRONE_SERVER
sẽ cấu hình cách tác nhân sẽ kết nối với thành phần server Drone. Nó sẽ bắt đầu với một tiền tố giao thức wss://
để cho biết rằng kết nối sẽ sử dụng một socket web được mã hóa theo sau là domain của server Drone với URI /ws/broker
nối vào cuối:
DRONE_SECRET=secret_generated_on_command_line DRONE_SERVER=wss://example.com/ws/broker
Lưu file khi bạn hoàn tất.
Cấu hình file đơn vị Drone Systemd
Bây giờ các file cấu hình của ta đã có sẵn, ta có thể xác định file đơn vị systemd để quản lý dịch vụ Drone.
Mở file .service
mới trong folder /etc/systemd/system
để cấu hình dịch vụ:
- sudo nano /etc/systemd/system/drone.service
Bên trong dán các nội dung sau:
[Unit] Description=Drone server After=docker.service nginx.service [Service] Restart=always ExecStart=/usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up ExecStop=/usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml stop [Install] WantedBy=multi-user.target
Phần đầu tiên yêu cầu systemd khởi động dịch vụ này sau khi có Docker và Nginx. Phần thứ hai yêu cầu hệ thống init tự động khởi động lại dịch vụ trong trường hợp bị lỗi. Sau đó, nó xác định các lệnh để bắt đầu và dừng dịch vụ Drone bằng Docker Compose và file cấu hình mà ta đã tạo trước đó. Cuối cùng, phần cuối cùng xác định cách kích hoạt dịch vụ khởi động khi server khởi động .
Lưu file khi bạn hoàn tất.
Trước khi bắt đầu dịch vụ Drone, ta phải cấu hình Nginx. Tác nhân Drone cần có khả năng kết nối với server Drone và kết nối dựa vào proxy Nginx đang có.
Cấu hình Nginx Để Yêu cầu Proxy để Drone
Tiếp theo, ta cần sửa đổi cấu hình của Nginx thành các yêu cầu proxy tới server Drone của ta .
Bắt đầu bằng cách tìm cấu hình khối server xử lý domain được bảo vệ bằng Let's Encrypt của bạn. Tìm kiếm thuộc tính server_name
trong tất cả các khối server đã bật bằng lệnh :
- grep -R server_name /etc/nginx/sites-enabled
Output/etc/nginx/sites-enabled/default: server_name example.com; /etc/nginx/sites-enabled/default: return 301 https://$server_name$request_uri; /etc/nginx/sites-enabled/default: server_name example.com; /etc/nginx/sites-enabled/default:# server_name example.com;
Trong kết quả ở trên, domain ( example.com
trong trường hợp này) đang được xác định trong file /etc/nginx/sites-enabled/default
. Bạn cần chỉnh sửa file (cột đầu tiên) được liên kết với domain của bạn.
Có thể bạn cũng có thể thấy thông tin như thế này:
Output/etc/nginx/sites-enabled/default: server_name _; /etc/nginx/sites-enabled/default: return 301 https://$server_name$request_uri; /etc/nginx/sites-enabled/default: server_name _; /etc/nginx/sites-enabled/default:# server_name example.com;
Trong kết quả ở trên, server_name _;
dòng đại diện cho các khối server nghĩa là hoạt động như cơ chế dự phòng. Mã định danh server “_” là server không hợp lệ, vì vậy nó sẽ không bao giờ tự khớp.
Trong cấu hình, chúng được ghép nối với các chỉ thị listen
đặt tùy chọn default_server
để khối hoạt động như một mặc định khi server được yêu cầu không trùng với bất kỳ khối server đã xác định nào khác. Nếu bạn không thể tìm thấy định nghĩa server_name
phù hợp với domain của bạn , bạn nên sử dụng file xác định các khối dự phòng này để thay thế.
Mở file được liên kết tốt nhất với domain của bạn trong editor của bạn:
- sudo nano /etc/nginx/sites-enabled/default
Bên trong, ta sẽ bắt đầu bằng cách thêm hai phần bên ngoài các khối server
hiện có:
upstream drone { server 127.0.0.1:8000; } map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { . . .
Khối đầu tiên cấu hình một vị trí ngược dòng được gọi là drone
nơi ta có thể yêu cầu proxy. Chỉ thị server
xác định cách kết nối với dịch vụ Drone của ta , dịch vụ này sẽ chạy trên cổng 8000.
Các bộ khối thứ hai một biến user định nghĩa gọi là $connection_upgrade
dựa trên giá trị của $http_upgrade
biến, mà bộ Nginx khi một “Nâng cấp” tiêu đề HTTP được nhận. Nếu nhận được tiêu đề Nâng cấp, Nginx sẽ đặt biến $connection_upgrade
connect_upgrade để upgrade
. Nếu không, nó sẽ đặt nó để close
. Các biến này cho phép ta cài đặt các tiêu đề chính xác khi ủy quyền các yêu cầu WebSocket.
Tiếp theo, tìm khối server
có chỉ thị listen 443
bên trong. Thay thế nội dung của location /
khối bằng các lệnh sau. Đảm bảo comment hoặc xóa bất kỳ cấu hình hiện có nào khỏi khối đó để tránh xung đột:
. . . server { listen 443 ssl; . . . location / { # try_files $uri $uri/ =404; proxy_pass http://drone; include proxy_params; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_redirect off; proxy_http_version 1.1; proxy_buffering off; chunked_transfer_encoding off; proxy_read_timeout 86400; } . . . }
Dòng proxy_pass
yêu cầu Nginx chuyển tất cả truy cập được phân phối ra khỏi khối này đến phần upstream
mà ta đã xác định trước đó. Tiếp theo, ta bao gồm một số định nghĩa tiêu đề proxy từ file proxy_params
và thêm các tiêu đề bổ sung dựa trên cài đặt map
của ta trước đó.
Sau đó, ta điều chỉnh một số cài đặt proxy cụ thể khác đảm bảo proxy WebSocket hoạt động chính xác và đảm bảo các thành phần của ta có thể giao tiếp hiệu quả.
Khi bạn hoàn tất, hãy lưu file .
Kiểm tra và khởi động lại Nginx và Drone
Cấu hình của ta hiện đã hoàn tất. Ta chỉ cần khởi động hoặc khởi động lại các dịch vụ của bạn để triển khai cấu hình.
Để bắt đầu, hãy kiểm tra cấu hình Nginx để biết lỗi cú pháp:
- sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Nếu kết quả cho biết đã có sự cố cấu hình, hãy quay lại và kiểm tra lại cấu hình Nginx.
Khi đã sẵn sàng tiếp tục, hãy khởi động lại Nginx:
- sudo systemctl restart nginx
Như vậy, Nginx có sẵn cho các yêu cầu proxy giữa tác nhân và server , ta có thể khởi động Drone:
- sudo systemctl start drone
Kiểm tra đảm bảo dịch vụ có thể khởi động thành công:
- sudo systemctl status drone
Output● drone.service - Drone server Loaded: loaded (/etc/systemd/system/drone.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2017-06-09 21:56:33 UTC; 2min 58s ago Main PID: 15225 (docker-compose) Tasks: 5 Memory: 37.7M CPU: 1.544s CGroup: /system.slice/drone.service ├─15225 /usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up └─15228 /usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up . . . Jun 09 21:56:35 drone docker-compose[15225]: drone-agent_1 | pipeline: request next execution
Nếu dịch vụ được đánh dấu là active (running)
và không có lỗi nào trong log , thì Drone đang hoạt động.
Nếu bạn gặp sự cố, bạn có thể kiểm tra log Nginx bằng lệnh :
- sudo less /var/log/nginx/error.log
Bạn có thể kiểm tra log Drone bằng lệnh :
- sudo journalctl -u drone
Nếu mọi thứ đang chạy chính xác, hãy cho phép Drone khởi động khi server khởi động bằng lệnh :
- sudo systemctl enable drone
Dịch vụ Drone sẽ khởi động sau khi dịch vụ Docker và Nginx khả dụng.
Đăng nhập vào Drone để cấp quyền truy cập vào repository của bạn
Bây giờ Drone đã được cài đặt và chạy, ta có thể đăng nhập vào giao diện web và cho phép ứng dụng sử dụng account GitHub của ta .
Truy cập domain của server trong trình duyệt web để xem giao diện web Drone:
https://example.com
Trong lần đầu tiên truy cập, bạn sẽ được yêu cầu đăng nhập:
Nhấp vào đăng nhập để xác thực Drone bằng account GitHub của bạn bằng OAuth. Nếu bạn hiện chưa đăng nhập vào GitHub, trước tiên bạn sẽ được hướng dẫn đăng nhập vào GitHub.
Sau đó, bạn sẽ được yêu cầu cho phép Drone truy cập vào account GitHub của bạn:
Sau khi xem xét các quyền được yêu cầu và thực hiện bất kỳ điều chỉnh nào, hãy nhấp vào nút Ủy quyền tên user để ủy quyền cho Drone.
Bạn sẽ được chuyển hướng trở lại server Drone của bạn :
Từ đây, bạn có thể kích hoạt và cấu hình repository của bạn để tự động kiểm tra mã của bạn.
Kết luận
Trong hướng dẫn này, ta cài đặt Drone làm server phân phối và tích hợp liên tục cho các dự án GitHub của ta . Ta đã cấu hình server Drone làm trung tâm trung tâm để ủy quyền công việc, xử lý xác thực và lắng nghe các thay đổi từ kho của ta . Ta cũng đã cấu hình một tác nhân Drone có thể chạy thử nghiệm và quản lý containers . Trước tất cả những điều này, ta đã cấu hình Nginx để hoạt động như một Reverse Proxy an toàn.
Khi đã sẵn sàng cài đặt Drone để tự động chạy thử nghiệm đối với repository của bạn , hãy xem tài liệu Drone để tìm hiểu cách xác định file .drone.yml
với các quy trình thử nghiệm của bạn.
Các tin liên quan
Cách giám sát cảnh báo Zabbix với Alerta trên Ubuntu 16.042017-06-13
Cách cài đặt và cấu hình Zabbix để giám sát an toàn server từ xa trên Ubuntu 16.04
2017-06-08
how-to-config-an-orientdb-cluster-on-ubuntu-16-04
2017-06-02
Cách cài đặt và cấu hình OpenLDAP và phpLDAPadmin trên Ubuntu 16.04
2017-06-01
Cách bật SFTP mà không cần truy cập Shell trên Ubuntu 16.04
2017-05-31
Cách tạo Go Executables cho nhiều nền tảng trên Ubuntu 16.04
2017-05-30
Cách cài đặt Concourse CI trên Ubuntu 16.04
2017-05-26
Cách giám sát server và dịch vụ bằng Icinga trên Ubuntu 16.04
2017-05-05
Cách thiết lập đồng bộ hóa thời gian trên Ubuntu 16.04
2017-04-28
Cách quản lý log với Graylog 2 trên Ubuntu 16.04
2017-04-25