Ansible copy module ใช้คัดลอกไฟล์จาก control node (เครื่องที่รัน Ansible) ไปยัง remote server หรือสร้างไฟล์จาก content ที่กำหนดโดยตรงใน Playbook เป็น module พื้นฐานที่ใช้บ่อยมากในงาน configuration management ตั้งแต่ deploy config files, certificates, ไปจนถึง scripts
บทความนี้อธิบายการใช้ copy module ครอบคลุมตั้งแต่การ copy ไฟล์พื้นฐาน, กำหนด permission, สร้างไฟล์จาก content, backup ไฟล์เดิม, ไปจนถึงความแตกต่างระหว่าง copy, template, และ synchronize module
Copy ไฟล์พื้นฐาน
Parameter หลักของ copy module คือ src (ไฟล์ต้นทางบน control node) และ dest (path ปลายทางบน remote server)
---
- name: Copy files to remote servers
hosts: webservers
become: true
tasks:
- name: Copy nginx config
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
- name: Copy SSL certificate
copy:
src: files/server.crt
dest: /etc/ssl/certs/server.crt
- name: Copy script
copy:
src: scripts/deploy.sh
dest: /opt/scripts/deploy.sh
ค่า src เป็น relative path จาก Playbook directory หรือจาก files/ subdirectory ของ role ถ้า src เป็น directory (ลงท้ายด้วย /) จะ copy เฉพาะ contents ข้างใน ถ้าไม่มี / จะ copy ทั้ง directory
กำหนด Owner, Group และ Permission
ใช้ owner, group, และ mode กำหนด file permission หลัง copy — ทำงานเหมือน chown และ chmod
---
- name: Copy with permissions
hosts: all
become: true
tasks:
- name: Copy config with correct owner
copy:
src: files/app.conf
dest: /etc/app/app.conf
owner: www-data
group: www-data
mode: '0644'
- name: Copy executable script
copy:
src: scripts/backup.sh
dest: /usr/local/bin/backup.sh
owner: root
group: root
mode: '0755' # executable
- name: Copy private key
copy:
src: files/private.key
dest: /etc/ssl/private/server.key
owner: root
group: ssl-cert
mode: '0640' # owner read/write, group read only
mode รองรับทั้ง octal format ('0644') และ symbolic format ('u=rw,g=r,o=r') ควรใส่ quotes รอบ octal เสมอเพื่อป้องกัน YAML ตีความเป็น integer
สร้างไฟล์จาก Content
แทนที่จะ copy จากไฟล์ สามารถใช้ content parameter เขียน text โดยตรงลงใน remote file เหมาะสำหรับไฟล์ขนาดเล็กหรือ config ที่ต้องการ inline
---
- name: Create files from content
hosts: all
become: true
tasks:
- name: Create motd file
copy:
content: |
Welcome to Production Server
Unauthorized access is prohibited.
All activities are monitored and logged.
dest: /etc/motd
owner: root
mode: '0644'
- name: Create simple config
copy:
content: "SERVER_ENV=production\nDEBUG=false\nLOG_LEVEL=info\n"
dest: /etc/app/env
mode: '0644'
- name: Create hosts entry
copy:
content: "192.168.1.10 app-server\n192.168.1.11 db-server\n"
dest: /etc/hosts.custom
mode: '0644'
Backup ไฟล์เดิมก่อน Overwrite
backup: yes สร้างไฟล์ backup ของเดิมพร้อม timestamp ก่อนที่จะ overwrite ป้องกันการสูญหายของ config เดิมเมื่อ deploy ใหม่
---
- name: Deploy with backup
hosts: webservers
become: true
tasks:
- name: Update nginx config with backup
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
backup: yes # สร้าง backup เช่น nginx.conf.2026-04-16@10:30~
owner: root
mode: '0644'
notify: reload nginx
- name: Update app config with backup
copy:
src: files/app.conf
dest: /etc/app/app.conf
backup: yes
handlers:
- name: reload nginx
service:
name: nginx
state: reloaded
ไฟล์ backup จะมีชื่อในรูปแบบ filename.YYYY-MM-DD@HH:MM~ เก็บไว้ใน directory เดิม เหมาะสำหรับ rollback manual ถ้า config ใหม่มีปัญหา
ตรวจสอบ Checksum และ Force Copy
โดย default copy module ตรวจ checksum ของไฟล์ปลายทางก่อน ถ้าเหมือนกับต้นทางจะ skip (idempotent) ใช้ force: no เพื่อ copy เฉพาะเมื่อไฟล์ยังไม่มีอยู่
---
- name: Checksum and force examples
hosts: all
become: true
tasks:
- name: Copy only if destination does not exist
copy:
src: files/default.conf
dest: /etc/app/app.conf
force: no # ไม่ overwrite ถ้าไฟล์มีอยู่แล้ว
- name: Always force overwrite
copy:
src: files/app.conf
dest: /etc/app/app.conf
force: yes # default behavior
- name: Validate file after copy
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
validate: nginx -t -c %s # ทดสอบ config ก่อน commit
validate parameter รัน command เพื่อตรวจสอบไฟล์ก่อนที่จะ copy ไปที่ปลายทางจริง %s จะถูกแทนด้วย path ของไฟล์ชั่วคราว ถ้า command return non-zero จะไม่ copy และ task จะ fail
Copy ทั้ง Directory
การ copy directory ต้องระวัง trailing slash ของ src เพราะมีผลต่อ structure ของ destination
---
- name: Copy directories
hosts: all
become: true
tasks:
# src มี trailing slash = copy เฉพาะ contents ข้างใน
- name: Copy config files into /etc/app/
copy:
src: files/app_config/ # trailing slash
dest: /etc/app/
owner: www-data
mode: '0644'
# src ไม่มี trailing slash = copy ทั้ง directory รวม folder name
- name: Copy entire app_config directory
copy:
src: files/app_config # ไม่มี trailing slash
dest: /etc/
# ผลลัพธ์: /etc/app_config/ พร้อม contents ข้างใน
copy vs template vs synchronize
มี 3 module สำหรับส่งไฟล์ไปยัง remote server แต่ละตัวมีจุดประสงค์ต่างกัน การเลือกใช้ให้ถูกต้องทำให้ Playbook มีประสิทธิภาพมากขึ้น
---
- name: Module comparison examples
hosts: webservers
become: true
vars:
server_name: "myapp.example.com"
app_port: 8080
tasks:
# copy: ไฟล์ static ไม่มี variable
- name: Copy static file (use copy)
copy:
src: files/robots.txt
dest: /var/www/html/robots.txt
# template: ไฟล์ที่มี Jinja2 variables
- name: Deploy nginx config with variables (use template)
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/myapp
# nginx.conf.j2 มี {{ server_name }} และ {{ app_port }}
# synchronize: sync directory ขนาดใหญ่ ใช้ rsync
- name: Sync web files (use synchronize)
synchronize:
src: /local/webapp/
dest: /var/www/html/
delete: yes # ลบไฟล์ปลายทางที่ไม่มีในต้นทาง
สรุปการเลือก module: ใช้ copy สำหรับไฟล์ static ขนาดเล็ก, ใช้ template เมื่อไฟล์มี variables ที่ต้อง render, และใช้ synchronize เมื่อต้อง sync directory ขนาดใหญ่เพราะใช้ rsync ที่เร็วกว่า
Pattern: Deploy Application Config
ตัวอย่าง Playbook สำหรับ deploy config files ไปยัง web server พร้อม permission ที่ถูกต้อง, backup ไฟล์เดิม, และ reload service เมื่อมีการเปลี่ยนแปลง
---
- name: Deploy Web Application Config
hosts: webservers
become: true
vars:
app_user: www-data
config_dir: /etc/myapp
tasks:
- name: Ensure config directory exists
file:
path: "{{ config_dir }}"
state: directory
owner: "{{ app_user }}"
mode: '0755'
- name: Copy main config
copy:
src: files/myapp.conf
dest: "{{ config_dir }}/myapp.conf"
owner: "{{ app_user }}"
group: "{{ app_user }}"
mode: '0640'
backup: yes
notify: restart myapp
- name: Copy SSL certificate
copy:
src: files/server.crt
dest: /etc/ssl/certs/myapp.crt
owner: root
group: ssl-cert
mode: '0644'
notify: reload nginx
- name: Copy SSL private key
copy:
src: files/server.key
dest: /etc/ssl/private/myapp.key
owner: root
group: ssl-cert
mode: '0640'
notify: reload nginx
- name: Copy maintenance page
copy:
content: "Maintenance in progress. Please try again later.\n"
dest: /var/www/html/maintenance.html
owner: "{{ app_user }}"
mode: '0644'
handlers:
- name: restart myapp
service:
name: myapp
state: restarted
- name: reload nginx
service:
name: nginx
state: reloaded
สรุป
copy module เป็นวิธีที่ถูกต้องสำหรับ deploy ไฟล์ static ไปยัง remote server ใน Ansible Pattern ที่ควรจำ: ใช้ owner, group, mode ทุกครั้งที่ deploy config ที่ sensitive, ใส่ backup: yes สำหรับไฟล์ที่อาจต้อง rollback, และใช้ validate parameter สำหรับ config ที่มี syntax check tool เช่น nginx หรือ apache
เลือก module ให้ถูกจุดประสงค์: copy สำหรับไฟล์ static, template เมื่อต้องการ Jinja2 variables, และ synchronize เมื่อต้อง sync directory ขนาดใหญ่ด้วย rsync

