Copy Module

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 direktori files/ 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 ke true, 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 archive menjadi file .tar.gz), lalu mengambil file kompresi tersebut menggunakan fetch.
  • Parameter flat mengontrol struktur penyimpanan file di control node kita. Jika flat: 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. Jika flat: 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:

  1. Perkakas rsync sudah terinstal di komputer lokal kita (control node) dan juga di server target (managed node).
  2. 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 template jika file konfigurasi berisi variabel dinamis (seperti alamat IP, nama host, atau port database).
  • Gunakan copy jika file bersifat statis dan ukurannya relatif kecil (seperti file sertifikat SSL, aset gambar tunggal, atau konfigurasi statis).
  • Gunakan synchronize jika kita perlu memindahkan direktori aset media yang besar atau melakukan sinkronisasi build aplikasi (dist folder) berisi ribuan file.
  • Gunakan fetch jika 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 parameter src modul copy dan synchronize untuk menghindari kesalahan pembuatan subfolder tujuan.
  • Cadangan Sebelum Update — Aktifkan backup: true pada modul copy untuk mengamankan salinan konfigurasi lama sebelum digantikan oleh file baru.
  • Unduh dengan Fetch — Gunakan modul fetch untuk menarik file tunggal dari server target, dan setel flat: false jika menarik dari banyak server sekaligus.
  • Kecepatan Rsync — Manfaatkan modul synchronize alih-alih copy untuk 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 file dengan state: directory untuk membuat folder, dan aktifkan recurse: true jika 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 copy untuk file konfigurasi yang memerlukan modifikasi nilai dinamis; gunakan modul template Jinja2.

← Sebelumnya: Service   Berikutnya: Template (Jinja2) →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact