write-configs
Fortinet: Writing Configs
Overview
This skill guides generating correct, ready-to-paste FortiOS CLI configuration blocks. Use it when the user asks to "add", "create", "change", "generate", or "update" FortiGate config.
See fortinet:read-configs for: fleet inventory, file paths, how to read existing config to inform what you're writing.
Always read the relevant existing config section before generating changes. You need to know existing object names, interface names, and IP schemes before producing CLI.
FortiOS CLI Conventions
- Named objects (interfaces, VPN tunnels, addresses):
edit "quoted-name" - Indexed objects (firewall policies, static routes):
edit <next-available-integer>— check existing config for the highest current integer, then add 1 - Always end entries with
next, end sections withend - Omit fields you aren't changing — FortiOS preserves existing values
- To modify an existing object:
config <section>→edit "existing-name"→set <fields>→next→end - Never include
set uuid— FortiOS auto-generates UUIDs - Encrypted secrets appear as
ENC <base64>in snapshots — never copy those; generate fresh PSKs
Firewall Policies
Required fields for a new accept policy:
config firewall policy
edit <N>
set name "descriptive-name"
set srcintf "SOURCE-INTERFACE"
set dstintf "DEST-INTERFACE"
set srcaddr "ADDRESS-OR-GROUP"
set dstaddr "ADDRESS-OR-GROUP"
set action accept
set schedule "always"
set service "SERVICE-OR-ALL"
set logtraffic all
next
end
Adding UTM inspection (required for internet-bound policies):
set utm-status enable
set inspection-mode flow
set profile-type single
set profile-protocol-options "default"
set ssl-ssh-profile "certificate-inspection"
set av-profile "default"
set webfilter-profile "default"
set ips-sensor "default"
set application-list "default"
Policy integer N: Grep existing config firewall policy block, find the highest edit N, use N+1.
Policy ordering: New policies are appended at the bottom. To reorder after creation: move N after M or move N before M.
Interfaces and VLANs
Modify an existing physical interface:
config system interface
edit "PORT-NAME"
set description "human-readable description"
set ip 10.X.X.X 255.255.255.0
set allowaccess ping https ssh
next
end
Create a VLAN subinterface:
config system interface
edit "PORT.VLANID"
set vdom "root"
set type vlan
set vlanid <ID>
set interface "PARENT-PORT"
set ip 10.X.X.X 255.255.255.0
set allowaccess ping https ssh
set description "VLAN description"
next
end
allowaccess values: ping, https, ssh, http, fgfm, snmp
- Management interfaces:
ping https ssh - WAN/transit interfaces:
pingonly (or omit entirely) - Never include
telnet— plaintext, never appropriate
Static Routes
config router static
edit <N>
set dst 10.X.X.X 255.255.255.0
set gateway 10.X.X.1
set device "INTERFACE-NAME"
set distance 10
set priority 1
set comment "why this route exists"
next
end
Default route:
config router static
edit <N>
set dst 0.0.0.0 0.0.0.0
set gateway <ISP-GATEWAY-IP>
set device "external"
set distance 10
next
end
VPN IPsec
Phase 1 (IKEv2, strong crypto — use for all new tunnels)
config vpn ipsec phase1-interface
edit "TUNNEL-NAME"
set type static
set interface "external"
set ike-version 2
set proposal aes256-sha256
set dhgrp 14
set authmethod psk
set peertype any
set remote-gw <REMOTE-IP>
set psksecret <SHARED-SECRET>
set dpd on-demand
set auto-negotiate enable
set keylife 28800
set comments "Description of this tunnel"
next
end
Phase 2
config vpn ipsec phase2-interface
edit "TUNNEL-NAME"
set phase1name "TUNNEL-NAME"
set proposal aes256-sha256
set dhgrp 14
set pfs enable
set keylifeseconds 3600
set src-subnet 0.0.0.0 0.0.0.0
set dst-subnet 0.0.0.0 0.0.0.0
next
end
Crypto standards for all new tunnels:
- Encryption:
aes256(minimumaes128) - Hash:
sha256orsha384— nevermd5, neversha1alone - DH group:
14minimum (2048-bit); prefer19or20for ECDH - IKE version: always
2
Do not copy existing fleet tunnel settings as a template. Some existing tunnels use aes128-sha1 and dhgrp 2 — those are known weak configs flagged by the audit skill.
Multi-Site Output
When the same change applies to multiple sites:
- Read the relevant section from each site's config to find site-specific values (IPs, interface names, current policy count)
- Generate one CLI block per site, labeled with a comment header
- Format:
# ============================================================
# CDW (cdwfw01)
# ============================================================
config system interface
edit "external"
set description "WAN uplink"
next
end
# ============================================================
# DAL (dalfw01)
# ============================================================
config system interface
edit "external"
set description "WAN uplink"
next
end
Verification Reminder
Always append this at the end of generated config output:
# VERIFY BEFORE APPLYING
# 1. SSH to the firewall
# 2. show <relevant section> — confirm current state
# 3. Paste the config above
# 4. show <relevant section> — confirm changes applied
# 5. To revert: re-enter the section and restore previous values