Copy Module #
Dalam administrasi server, pengelolaan file dan direktori adalah salah satu tugas yang paling krusial. Kita perlu menyalin file konfigurasi statis, mengunggah sertifikat SSL, membackup direktori data, membuat folder baru untuk aplikasi, atau mengambil log dari server target ke komputer lokal kita. Ansible menyediakan serangkaian modul pengelolaan file yang sangat lengkap, seperti ansible.builtin.copy, ansible.builtin.fetch, dan ansible.posix.synchronize. Memahami cara kerja masing-masing modul serta aspek keamanan berkas (permission dan ownership) memastikan bahwa transfer berkas berjalan secara aman, efisien, dan idempoten di seluruh infrastruktur kita.
Mengunggah File Statis dengan Module copy #
Modul ansible.builtin.copy digunakan untuk menyalin berkas dari komputer lokal kita (control node) ke server tujuan (managed node). Modul ini bekerja di atas protokol SFTP atau SCP bawaan koneksi SSH.
Beberapa parameter terpenting dari modul copy yang harus kita kuasai meliputi:
src: Menentukan lokasi file sumber di control node. Jalur ini bisa berupa jalur absolut atau relatif. Jika kita menggunakannya di dalam role, Ansible secara otomatis akan mencari file tersebut di dalam direktorifiles/milik role tersebut.dest: Menentukan lokasi tujuan di managed node. Parameter ini wajib diisi dengan jalur absolut (misalnya/etc/nginx/nginx.conf).backup: Jika disetel ketrue, Ansible akan membuat salinan cadangan dari file yang sudah ada di server tujuan sebelum menimpanya dengan file baru. File cadangan ini akan dinamai dengan timestamp (misalnya/etc/nginx/nginx.conf.12345.2026-06-17@14:00~).content: Opsi alternatif untuk membuat file secara langsung dengan mengisikan teks inline di dalam playbook kita tanpa perlu membuat file fisik di control node.
Salah satu detail kecil dalam penggunaan parameter src yang sering menimbulkan kebingungan adalah penggunaan garis miring di akhir folder (trailing slash /). Jika kita menyalin folder dan menyertakan trailing slash (misalnya src: files/static/), Ansible hanya akan menyalin isi dari folder tersebut ke tujuan. Namun, jika kita tidak menyertakan trailing slash (misalnya src: files/static), Ansible akan menyalin folder itu sendiri beserta isinya (membuat folder static di dalam tujuan).
Mari kita pelajari contoh implementasi berikut untuk menghindari hilangnya konfigurasi lama:
# ANTI-PATTERN: Menyalin file konfigurasi tanpa membuat cadangan (backup), berisiko kehilangan konfigurasi asli jika rusak
- name: Salin file config aplikasi
copy:
src: files/app.conf
dest: /etc/app/app.conf
# BENAR: Menggunakan backup: yes untuk menyimpan versi lama sebelum ditimpa secara otomatis oleh Ansible
- name: Salin file config aplikasi dengan cadangan aman
copy:
src: files/app.conf
dest: /etc/app/app.conf
backup: true
Kita juga dapat menggunakan parameter content untuk menuliskan file-file kecil yang dinamis atau file konfigurasi sederhana tanpa perlu memelihara banyak file fisik di repositori git kita:
- name: Buat file konfigurasi lingkungan aplikasi secara inline
copy:
content: |
DB_HOST=127.0.0.1
DB_PORT=5432
LOG_LEVEL=info
DEBUG=false
dest: /opt/myapp/.env
owner: myapp
group: myapp
mode: '0600' # Akses terbatas hanya untuk pemilik file demi keamanan
Mengambil Berkas dari Managed Node dengan Module fetch #
Jika modul copy bertugas mengunggah file dari komputer kita ke server, modul ansible.builtin.fetch melakukan pekerjaan sebaliknya. Modul ini digunakan untuk mengunduh (menarik) berkas dari managed node ke control node kita. Ini sangat berguna ketika kita ingin mengumpulkan file log sistem, mengambil sertifikat SSL yang di-generate di server, atau mengamankan file backup database ke komputer kita.
Ada beberapa aturan penting terkait penggunaan modul fetch:
- Modul ini hanya dapat mengambil file tunggal, bukan direktori. Jika kita perlu mengambil satu direktori penuh beserta isinya, kita harus mengompresnya terlebih dahulu di server (misalnya menggunakan modul
archivemenjadi file.tar.gz), lalu mengambil file kompresi tersebut menggunakanfetch. - Parameter
flatmengontrol struktur penyimpanan file di control node kita. Jikaflat: false(default), Ansible akan membuat struktur subdirektori berdasarkan nama host (inventory_hostname) dan jalur absolut file tersebut di server tujuan untuk mencegah file saling menimpa jika kita mengambil file dari banyak server sekaligus. Jikaflat: true, file akan langsung disimpan di jalur tujuan yang kita tentukan tanpa membuat folder nama host.
Berikut adalah contoh penggunaan modul fetch untuk mengumpulkan log diagnostik:
# Skenario 1: Mengambil file log error dari banyak server sekaligus (flat: false)
- name: Unduh log error dari seluruh klaster server
fetch:
src: /var/log/nginx/error.log
dest: logs/nginx/
flat: false
# Skenario 2: Mengambil file sertifikat dari satu host tertentu (flat: true)
- name: Ambil sertifikat Let's Encrypt dari server web utama
fetch:
src: /etc/letsencrypt/live/example.com/fullchain.pem
dest: backups/certs/example.com.fullchain.pem
flat: true
Output dari skenario pertama akan menghasilkan struktur folder lokal kita sebagai berikut:
logs/
└── nginx/
├── web-01/
│ └── var/log/nginx/error.log
└── web-02/
└── var/log/nginx/error.log
Struktur ini memastikan file log dari web-01 tidak akan pernah menimpa file log milik web-02 meskipun nama berkasnya sama-sama error.log.
Transfer File Skala Besar dengan Module synchronize (rsync) #
Modul copy bawaan Ansible sangat andal untuk transfer file kecil, namun ia memiliki kelemahan performa yang signifikan jika digunakan untuk memindahkan berkas yang sangat besar (berukuran gigabyte) atau direktori yang berisi puluhan ribu berkas kecil (seperti folder aset gambar atau kode aplikasi). Hal ini terjadi karena modul copy memproses transfer berkas menggunakan Python melalui paket SFTP satu per satu, sehingga menciptakan overhead latensi jaringan yang besar.
Untuk mengatasi kendala performa ini, Ansible menyediakan modul ansible.posix.synchronize. Modul ini merupakan pembungkus (wrapper) dari perkakas populer rsync di Linux. rsync menggunakan algoritma delta-transfer yang hanya mengirimkan perbedaan (perubahan) berkas antara sumber dan tujuan, melakukan kompresi data selama transfer, dan mengoptimalkan koneksi SSH secara maksimal.
Namun, untuk menggunakan modul synchronize, kita harus memastikan bahwa:
- Perkakas
rsyncsudah terinstal di komputer lokal kita (control node) dan juga di server target (managed node). - Autentikasi SSH berbasis kunci (SSH Key) sudah terkonfigurasi dengan benar karena modul ini akan menginisiasi koneksi rsync langsung di luar Ansible.
flowchart LR
subgraph "Control Node (Local Machine)"
A["Source File / Dir"]
end
subgraph "Managed Node (Remote Server)"
B["Destination Path"]
end
A -- "copy module (SFTP/SCP packets)" --> B
B -- "fetch module (pull file)" --> A
A -. "synchronize module (rsync protocol)" .-> B
Mari kita lihat perbandingan efisiensi sinkronisasi aset web statis menggunakan modul synchronize:
# Menggunakan synchronize untuk mengunggah direktori media secara efisien
- name: Sinkronkan direktori media statis ke server web
synchronize:
src: /local/data/media/
dest: /var/www/myapp/media/
recursive: true
delete: true # Hapus file di server tujuan jika sudah tidak ada di server lokal kita
compress: true # Aktifkan kompresi gzip selama transfer data
Parameter delete: true sangat penting jika kita ingin memastikan direktori di server tujuan benar-benar identik dengan direktori lokal kita. Setiap file sampah di server target yang sudah kita hapus di server lokal akan dibersihkan secara otomatis oleh rsync. Ini sangat membantu menjaga efisiensi ruang penyimpanan disk di server.
Pengaturan Hak Akses: Permissions, Ownership, dan Security Context #
Ketika kita menyalin atau membuat berkas baru di Linux, kita wajib mengatur siapa pemilik berkas tersebut (owner), grup kepemilikannya (group), dan hak akses bit izinnya (mode). Salah mengonfigurasi bit izin dapat menyebabkan aplikasi tidak dapat membaca file (permission denied) atau sebaliknya, mengekspos file rahasia ke publik (security vulnerability).
Ansible mendukung pendefinisian bit izin menggunakan notasi oktal (octal notation). Ada satu perangkap sintaksis YAML yang sangat berbahaya di sini: selalu bungkus notasi oktal dalam tanda kutip tunggal (seperti '0644').
Jika kita menuliskan angka oktal tanpa tanda kutip (misalnya mode: 0644), parser YAML akan menganggap angka tersebut sebagai bilangan bulat oktal (octal integer) dan program Python di latar belakang secara otomatis akan mengonversinya menjadi bilangan desimal 420. Hasilnya, di server target, file kita akan mendapatkan permission mode: -r-x-w---- yang sepenuhnya rusak dan dapat merusak layanan sistem.
Mari kita pelajari contoh konfigurasi hak akses yang aman:
# Mengatur hak akses file konfigurasi dan direktori dengan notasi oktal string yang aman
- name: Deploy file kunci SSH private
copy:
src: files/id_rsa
dest: /home/deployer/.ssh/id_rsa
owner: deployer
group: deployer
mode: '0600' # Wajib menggunakan tanda kutip tunggal!
- name: Pastikan direktori logs ada dengan hak akses yang tepat
file:
path: /var/log/myapp
state: directory
owner: myapp
group: myapp
mode: '0750' # Pemilik bisa read/write/execute, grup bisa read/execute, others diblokir total
Notasi oktal '0644' berarti:
6(Owner): Read dan Write (4 + 2)4(Group): Read (4)4(Others): Read (4)
Sedangkan '0755' berarti:
7(Owner): Read, Write, dan Execute (4 + 2 + 1)5(Group): Read dan Execute (4 + 1)5(Others): Read dan Execute (4 + 1)
Validasi Berkas Sebelum Overwrite #
Sama seperti pada modul template, modul copy juga mendukung parameter validate. Validasi pra-penulisan (pre-overwrite validation) adalah teknik defensif terbaik untuk memastikan kita tidak pernah merusak layanan penting akibat kesalahan konfigurasi statis yang kita unggah.
Ketika kita menyertakan perintah validasi (misalnya nginx -t -c %s), Ansible akan menyalin file baru kita ke direktori sementara di server target, menjalankan perintah validasi pada file sementara tersebut, dan memeriksa kode status keluaran (exit code). Jika validasi berhasil, file sementara akan dipindahkan ke file tujuan (dest). Jika gagal, file tujuan yang asli tetap dipertahankan dan playbook akan dihentikan dengan pesan error yang detail.
Berikut adalah contoh implementasi validasi pada file konfigurasi Nginx dan konfigurasi SSH daemon:
# Mengunggah konfigurasi Nginx statis dengan validasi sintaksis sebelum diterapkan
- name: Salin file konfigurasi utama nginx.conf
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
validate: 'nginx -t -c %s'
notify: Reload Nginx
# Mengunggah konfigurasi SSH daemon dengan validasi sshd
- name: Deploy konfigurasi SSH hardening
copy:
src: files/sshd_config
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: '0600'
validate: '/usr/sbin/sshd -t -f %s'
notify: Restart SSH
Melakukan validasi pada sshd_config sangat krusial. Jika kita mengunggah file sshd_config yang rusak dan SSH daemon mengalami crash saat direstart, kita akan kehilangan akses SSH ke server selamanya dan tidak dapat melakukan perbaikan dari jarak jauh.
Kapan Memilih copy vs fetch vs synchronize vs template #
Untuk memudahkan proses pengambilan keputusan desain dalam playbook kita, berikut adalah tabel perbandingan komprehensif antara modul-modul transfer berkas yang tersedia di Ansible:
| Kriteria | Modul copy |
Modul fetch |
Modul synchronize |
Modul template |
|---|---|---|---|---|
| Arah Aliran | Push (Control -> Managed) | Pull (Managed -> Control) | Push atau Pull (Dinamis) | Push (Control -> Managed) |
| Dukungan Variabel | Tidak (Hanya teks statis) | Tidak | Tidak | Ya (Jinja2 Rendering) |
| Kinerja File Besar | Lambat | Lambat | Sangat Cepat (rsync) | Lambat |
| Dukungan Direktori | Ya (Menggunakan Python) | Tidak (Hanya file tunggal) | Ya (Sangat Efisien) | Tidak (Hanya file tunggal) |
| Dependency Sistem | Python bawaan | Python bawaan | Perkakas rsync terinstal |
Python bawaan |
| Fitur Backup | Ya (backup: true) |
Tidak | Tidak | Ya (backup: true) |
Sebagai aturan praktis:
- Gunakan
templatejika file konfigurasi berisi variabel dinamis (seperti alamat IP, nama host, atau port database). - Gunakan
copyjika file bersifat statis dan ukurannya relatif kecil (seperti file sertifikat SSL, aset gambar tunggal, atau konfigurasi statis). - Gunakan
synchronizejika kita perlu memindahkan direktori aset media yang besar atau melakukan sinkronisasi build aplikasi (dist folder) berisi ribuan file. - Gunakan
fetchjika kita perlu mengambil data diagnostik atau backup database dari server target ke komputer lokal kita.
Studi Kasus: Sinkronisasi dan Backup Aset Web Statis #
Mari kita buat sebuah skenario terintegrasi di mana kita mendeploy struktur direktori situs web statis baru, menyinkronkan file aset gambar yang besar dari folder build lokal kita menggunakan synchronize, mengunggah konfigurasi Nginx dengan validasi sintaksis dan backup otomatis, lalu mengunduh file log akses dari server untuk kebutuhan pelaporan internal.
Berikut adalah isi dari playbook integratif kita (playbooks/deploy-web-assets.yml):
# playbooks/deploy-web-assets.yml
---
- name: Otomasi Deployment Aset Web dan Backup Log
hosts: webservers
become: true
vars:
web_root: "/var/www/my-static-site"
local_build_dir: "/home/developer/project/build"
log_dir: "/var/log/nginx"
tasks:
# 1. Pastikan struktur direktori web root sudah ada di server
- name: Buat direktori root web secara rekursif
file:
path: "{{ web_root }}"
state: directory
owner: www-data
group: www-data
mode: '0755'
recurse: true
# 2. Sinkronkan folder aset gambar/HTML dari build lokal kita ke server (efisien)
- name: Sinkronkan seluruh aset build lokal ke web root server
synchronize:
src: "{{ local_build_dir }}/"
dest: "{{ web_root }}/"
recursive: true
delete: true # Hapus file usang di server yang tidak ada di build lokal
compress: true
notify: Reload Nginx
# 3. Salin konfigurasi virtual host Nginx statis dengan backup dan validasi
- name: Deploy konfigurasi virtual host Nginx
copy:
src: files/vhost-static.conf
dest: /etc/nginx/sites-available/vhost-static.conf
owner: root
group: root
mode: '0644'
backup: true # Simpan cadangan konfigurasi vhost lama jika ada perubahan
validate: 'nginx -t -c %s'
notify:
- Buat symlink vhost
- Reload Nginx
# 4. Ambil log akses Nginx dari server ke lokal untuk kebutuhan audit
- name: Tarik file access.log dari server target ke control node kita
fetch:
src: "{{ log_dir }}/access.log"
dest: "backups/logs/nginx/"
flat: false
handlers:
- name: Buat symlink vhost
file:
src: /etc/nginx/sites-available/vhost-static.conf
dest: /etc/nginx/sites-enabled/vhost-static.conf
state: link
- name: Reload Nginx
systemd:
name: nginx
state: reloaded
Dalam studi kasus ini, kita melihat bagaimana kombinasi modul-modul file management bekerja secara harmonis. file membuat folder, synchronize mengunggah aset berukuran besar secara instan, copy mendeploy konfigurasi sensitif dengan jaminan keamanan backup dan validasi visudo-style, sementara fetch menarik file data kembali ke server lokal kita dengan struktur folder yang aman dan terisolasi per hostname server.
Ringkasan #
- Pola Trailing Slash — Perhatikan akhiran garis miring
/pada parametersrcmodulcopydansynchronizeuntuk menghindari kesalahan pembuatan subfolder tujuan.- Cadangan Sebelum Update — Aktifkan
backup: truepada modulcopyuntuk mengamankan salinan konfigurasi lama sebelum digantikan oleh file baru.- Unduh dengan Fetch — Gunakan modul
fetchuntuk menarik file tunggal dari server target, dan setelflat: falsejika menarik dari banyak server sekaligus.- Kecepatan Rsync — Manfaatkan modul
synchronizealih-alihcopyuntuk mentransfer direktori besar atau ribuan file guna menghemat bandwidth dan waktu.- Perangkap YAML Oktal — Selalu bungkus bit izin permission (seperti
'0644') dalam tanda kutip tunggal agar YAML tidak merusak bit izin tersebut menjadi angka desimal acak.- Hak Akses Folder — Gunakan modul
filedenganstate: directoryuntuk membuat folder, dan aktifkanrecurse: truejika ingin permission diturunkan ke subfolder.- Validasi Konfigurasi — Sertakan perintah validasi seperti
validate: 'nginx -t -c %s'untuk memeriksa sintaksis file konfigurasi sebelum Ansible menyimpannya secara permanen.- Gunakan Template untuk Variabel — Jangan gunakan
copyuntuk file konfigurasi yang memerlukan modifikasi nilai dinamis; gunakan modultemplateJinja2.