11#! /bin/bash
22# =========================================
3- # DELETE WIREGUARD USER + AUTO EXPIRE CLEANUP - IMPROVED
3+ # DELETE WIREGUARD USER + AUTO EXPIRE CLEANUP
44# =========================================
55
66# ---------- Colors ----------
@@ -11,265 +11,200 @@ blue='\e[1;34m'
1111white=' \e[1;37m'
1212nc=' \e[0m'
1313
14- # ---------- Configuration ----------
14+ # ---------- Config ----------
1515readonly WG_CONF=" /etc/wireguard/wg0.conf"
1616readonly CLIENT_DIR=" /etc/wireguard/clients"
1717readonly BACKUP_DIR=" /etc/wireguard/backups"
18+ readonly EXPIRY_DB=" /etc/wireguard/user_expiry.db"
19+ readonly LOG_DIR=" /var/log/wireguard"
20+ readonly LOG_FILE=" $LOG_DIR /user-management.log"
1821
19- # ---------- Functions ----------
22+ # ---------- Helpers ----------
2023log_error () { echo -e " ${red} ❌ $1 ${nc} " ; }
2124log_success () { echo -e " ${green} ✅ $1 ${nc} " ; }
2225log_warn () { echo -e " ${yellow} ⚠️ $1 ${nc} " ; }
2326log_info () { echo -e " ${blue} ℹ️ $1 ${nc} " ; }
2427
25- # ---------- Validation Functions ----------
28+ # ---------- Validation ----------
2629validate_environment () {
27- if [[ ! -f " $WG_CONF " ]]; then
28- log_error " WireGuard configuration not found: $WG_CONF "
29- exit 1
30- fi
31-
32- if [[ ! -d " $CLIENT_DIR " ]]; then
33- log_warn " Client directory not found, creating: $CLIENT_DIR "
34- mkdir -p " $CLIENT_DIR "
35- fi
36-
37- mkdir -p " $BACKUP_DIR "
30+ [[ -f " $WG_CONF " ]] || { log_error " Config not found: $WG_CONF " ; exit 1; }
31+ mkdir -p " $CLIENT_DIR " " $BACKUP_DIR " " $LOG_DIR "
32+ chmod 700 " $LOG_DIR "
3833}
3934
4035backup_config () {
4136 local backup_file=" $BACKUP_DIR /wg0.conf.backup.$( date +%Y%m%d_%H%M%S) "
4237 cp " $WG_CONF " " $backup_file "
43- log_info " Config backed up to : $backup_file "
38+ log_info " Backup created : $backup_file "
4439}
4540
46- # ---------- Function: Delete Specific User ----------
41+ # ---------- Delete a Specific User ----------
4742delete_user () {
4843 local user=$1
49- local line_start line_end peer_block public_key
50-
44+ local line_start line_end public_key client_config
45+
5146 log_info " Searching for user: $user "
52-
53- # Find the comment line marking the user
54- line_start=$( grep -n " ^# $user \$ " " $WG_CONF " | cut -d: -f1)
55-
47+
48+ # Cari baris komentar user (# user ... )
49+ line_start=$( grep -n -m1 -E " ^# $user ( |-|$)" " $WG_CONF " | cut -d: -f1)
5650 if [[ -z " $line_start " ]]; then
57- log_error " User '$user ' not found in configuration! "
51+ log_error " User '$user ' not found in wg0.conf "
5852 return 1
5953 fi
60-
61- # Extract public key for verification
62- public_key=$( sed -n " $(( line_start+ 1 )) ,$(( line_start+ 10 )) p" " $WG_CONF " | grep " PublicKey" | awk ' {print $3}' )
63-
64- if [[ -z " $public_key " ]]; then
65- log_warn " Could not extract public key for user '$user '"
66- fi
67-
68- # Find the end of the peer block (next empty line or end of file)
69- line_end=$(( line_start + 1 ))
70- while IFS= read -r line; do
71- if [[ -z " $line " ]] || [[ " $line " =~ ^# ]] || [[ "$line" =~ ^\[Peer\] ]]; then
72- break
73- fi
74- (( line_end++ ))
75- done < < (tail -n +$(( line_start + 2 )) " $WG_CONF " )
76-
77- # Create backup before modification
54+
55+ # Ambil public key user
56+ public_key=$( awk " NR>$line_start && /PublicKey/{print \$ 3; exit}" " $WG_CONF " )
57+
58+ # Cari batas akhir blok peer berikutnya atau EOF
59+ line_end=$( awk -v start=" $line_start " ' NR>start && /^\[Peer\]/{print NR-1; exit}' " $WG_CONF " )
60+ [[ -z " $line_end " ]] && line_end=$( wc -l < " $WG_CONF " )
61+
7862 backup_config
79-
80- # Remove the peer block
81- log_info " Removing configuration lines $line_start to $line_end "
63+
64+ log_info " Deleting config lines $line_start to $line_end ..."
8265 sed -i " ${line_start} ,${line_end} d" " $WG_CONF "
83-
84- # Remove client config file
85- local client_config= " $CLIENT_DIR /$user .conf"
66+ sed -i ' /^$/N;/^\n$/D' " $WG_CONF "
67+
68+ # Hapus file client
69+ client_config=" $CLIENT_DIR /$user .conf"
8670 if [[ -f " $client_config " ]]; then
87- # Backup client config before deletion
8871 local client_backup=" $BACKUP_DIR /client_${user} _$( date +%Y%m%d_%H%M%S) .conf"
8972 cp " $client_config " " $client_backup "
9073 rm -f " $client_config "
91- log_info " Client config backed up and removed: $client_config "
92- else
93- log_warn " Client config file not found: $client_config "
74+ log_info " Client config removed and backed up"
9475 fi
95-
96- # Remove from running configuration if service is active
76+
77+ # Hapus dari konfigurasi aktif (jika service aktif)
9778 if systemctl is-active --quiet wg-quick@wg0 && [[ -n " $public_key " ]]; then
98- log_info " Removing peer from running configuration... "
99- wg set wg0 peer " $public_key " remove
79+ wg set wg0 peer " $public_key " remove 2> /dev/null || true
80+ log_info " Removed from active WireGuard session "
10081 fi
101-
102- log_success " User ' $user ' has been successfully deleted "
103-
104- # Log the deletion
105- echo " [$( date ' +%Y-%m-%d %H:%M:%S' ) ] DELETED: $user (PublicKey: ${public_key:- UNKNOWN} )" >> /var/log/wireguard/user-management.log
106-
82+
83+ # Hapus dari database expiry (jika ada)
84+ [[ -f " $EXPIRY_DB " ]] && sed -i " /^ $user |/d " " $EXPIRY_DB "
85+
86+ echo " [$( date ' +%Y-%m-%d %H:%M:%S' ) ] DELETED: $user (PublicKey: ${public_key:- UNKNOWN} )" >> " $LOG_FILE "
87+ log_success " User ' $user ' deleted successfully! "
10788 return 0
10889}
10990
110- # ---------- Function: Auto Delete Expired Users ----------
91+ # ---------- Delete Expired Users ----------
11192delete_expired_users () {
112- log_info " Checking for expired WireGuard users..."
113-
114- local today expired_count=0
93+ log_info " Checking expired users..."
94+ [[ -f " $EXPIRY_DB " ]] || { log_warn " No expiry database found." ; return 0; }
95+
96+ local today expired=0
11597 today=$( date +%Y-%m-%d)
116-
117- # Check if expiry tracking file exists
118- local expiry_file=" /etc/wireguard/user_expiry.db"
119- if [[ ! -f " $expiry_file " ]]; then
120- log_warn " No expiry database found. Create users with expiry dates first."
121- return 0
122- fi
123-
124- # Process expiry database
98+
12599 while IFS=' |' read -r user expiry_date public_key; do
126- if [[ -n " $user " && -n " $expiry_date " ]]; then
127- if [[ " $expiry_date " < " $today " ]]; then
128- log_warn " User '$user ' expired on $expiry_date . Deleting..."
129- if delete_user " $user " ; then
130- # Remove from expiry database
131- sed -i " /^$user |/d" " $expiry_file "
132- (( expired_count++ ))
133- fi
134- fi
100+ [[ -z " $user " || -z " $expiry_date " ]] && continue
101+ if [[ $( date -d " $expiry_date " +%s) -lt $( date -d " $today " +%s) ]]; then
102+ log_warn " User '$user ' expired ($expiry_date ) → deleting..."
103+ delete_user " $user " && (( expired++ ))
135104 fi
136- done < " $expiry_file "
137-
138- if [[ $expired_count -eq 0 ]]; then
139- log_success " No expired users found"
140- else
141- log_success " Cleaned up $expired_count expired users"
142- fi
105+ done < " $EXPIRY_DB "
106+
107+ [[ $expired -eq 0 ]] && log_success " No expired users found" || log_success " Removed $expired expired users"
143108}
144109
145- # ---------- Function: List All Users ----------
110+ # ---------- List All Users ----------
146111list_all_users () {
147- log_info " Current WireGuard users:"
112+ log_info " WireGuard users:"
148113 echo -e " ${yellow} =========================================${nc} "
149-
150- local user_count=0
151- if [[ -f " /etc/wireguard/user_expiry.db " ]]; then
114+ local count=0 today= $( date +%Y-%m-%d )
115+
116+ if [[ -f " $EXPIRY_DB " ]]; then
152117 while IFS=' |' read -r user expiry_date public_key; do
153- if [[ -n " $user " ]]; then
154- local status=" Active"
155- if [[ " $expiry_date " < " $( date +%Y-%m-%d) " ]]; then
156- status=" ${red} EXPIRED${nc} "
157- fi
158- echo -e " 👤 $user | 📅 Expiry: $expiry_date | $status "
159- (( user_count++ ))
118+ [[ -z " $user " ]] && continue
119+ local status=" ${green} Active${nc} "
120+ if [[ $( date -d " $expiry_date " +%s) -lt $( date -d " $today " +%s) ]]; then
121+ status=" ${red} Expired${nc} "
160122 fi
161- done < " /etc/wireguard/user_expiry.db"
123+ echo -e " 👤 $user | 📅 Expiry: $expiry_date | $status "
124+ (( count++ ))
125+ done < " $EXPIRY_DB "
162126 fi
163-
164- # Also show users from config file without expiry
165- grep " ^# " " $WG_CONF " | grep -v " ^# \[Interface\]" | while read -r comment; do
166- user=$( echo " $comment " | awk ' {print $2}' )
167- if ! grep -q " ^$user |" " /etc/wireguard/user_expiry.db" 2> /dev/null; then
168- echo -e " 👤 $user | 📅 Expiry: ${yellow} NOT SET${nc} "
169- (( user_count++ ))
170- fi
127+
128+ # Tambahkan user tanpa expiry
129+ grep " ^# " " $WG_CONF " | grep -v " Interface" | while read -r comment; do
130+ local uname
131+ uname=$( echo " $comment " | awk ' {print $2}' )
132+ grep -q " ^$uname |" " $EXPIRY_DB " 2> /dev/null || {
133+ echo -e " 👤 $uname | 📅 Expiry: ${yellow} NOT SET${nc} "
134+ (( count++ ))
135+ }
171136 done
172-
173- if [[ $user_count -eq 0 ]]; then
174- echo -e " ${yellow} No users found${nc} "
175- fi
137+
138+ [[ $count -eq 0 ]] && echo -e " ${yellow} No users found${nc} "
176139 echo -e " ${yellow} =========================================${nc} "
177140}
178141
179- # ---------- Function: Confirm Deletion ----------
180- confirm_deletion () {
142+ # ---------- Confirm Delete ----------
143+ confirm_delete () {
181144 local user=$1
182145 echo
183- log_warn " ⚠️ You are about to delete user: $user "
184- echo -e " ${red} This action cannot be undone!${nc} "
146+ log_warn " ⚠️ You are about to delete user ' $user ' "
147+ echo -e " ${red} This cannot be undone!${nc} "
185148 echo
186- read -rp " Are you sure? (y/N): " confirmation
187- case " $confirmation " in
188- [yY]|[yY][eE][sS])
189- return 0
190- ;;
191- * )
192- log_info " Deletion cancelled"
193- return 1
194- ;;
195- esac
149+ read -rp " Confirm delete (y/N): " confirm
150+ [[ " $confirm " =~ ^[Yy]$ ]]
196151}
197152
198- # ---------- Main Menu ----------
153+ # ---------- Menu ----------
199154show_menu () {
200155 clear
201156 echo -e " ${red} =========================================${nc} "
202- echo -e " ${blue} ⚙️ WireGuard User Management ${nc} "
157+ echo -e " ${blue} ⚙️ WireGuard User Management ${nc} "
203158 echo -e " ${red} =========================================${nc} "
204159 list_all_users
205160 echo
206- echo -e " ${white} 1${nc} ) Delete a specific user"
161+ echo -e " ${white} 1${nc} ) Delete specific user"
207162 echo -e " ${white} 2${nc} ) Auto-delete expired users"
208- echo -e " ${white} 3${nc} ) List all users with expiry "
163+ echo -e " ${white} 3${nc} ) Refresh user list "
209164 echo -e " ${red} =========================================${nc} "
210165 echo -e " ${white} 0${nc} ) Back to main menu"
211166 echo -e " Press ${yellow} x${nc} or Ctrl+C to exit"
212167 echo -e " ${red} =========================================${nc} "
213168}
214169
215- # ---------- Main Execution ----------
170+ # ---------- Main ----------
216171main () {
217172 validate_environment
218-
219- local restart_needed=false
220- local opt
221-
173+ local opt restart_needed=false
222174 show_menu
223- read -rp " Select an option [0-3]: " opt
175+ read -rp " Select option [0-3]: " opt
224176
225177 case " $opt " in
226178 1)
227- read -rp " Enter username to delete: " user
228- if [[ -n " $user " ]]; then
229- if confirm_deletion " $user " ; then
230- delete_user " $user " && restart_needed=true
231- fi
232- else
233- log_error " Username cannot be empty"
179+ read -rp " Enter username: " user
180+ if [[ -n " $user " ]] && confirm_delete " $user " ; then
181+ delete_user " $user " && restart_needed=true
234182 fi
235183 ;;
236184 2)
237- if delete_expired_users; then
238- restart_needed=true
239- fi
185+ delete_expired_users && restart_needed=true
240186 ;;
241187 3)
242- # Just show the list and refresh menu
243188 read -n 1 -s -r -p " Press any key to continue..."
244- main
245- return
189+ main; return
246190 ;;
247191 0)
248- clear
249- m-wg
250- return
251- ;;
192+ clear; m-wg; return ;;
252193 * )
253- log_error " Invalid option!"
254- sleep 1
255- main
256- return
257- ;;
194+ log_error " Invalid option!" ; sleep 1; main; return ;;
258195 esac
259196
260- # ---------- Restart WireGuard if needed ----------
261- if [[ " $restart_needed " = true ]]; then
262- log_info " Applying configuration changes..."
197+ if [[ " $restart_needed " == true ]]; then
198+ log_info " Reloading WireGuard..."
263199 if systemctl reload-or-restart wg-quick@wg0; then
264- log_success " WireGuard service reconfigured successfully"
200+ log_success " WireGuard reloaded successfully"
265201 else
266- log_error " Failed to restart WireGuard service "
202+ log_error " WireGuard reload failed! "
267203 fi
268204 fi
269205
270- read -n 1 -s -r -p " Press any key to return to menu ..."
206+ read -n 1 -s -r -p " Press any key to return..."
271207 main
272208}
273209
274- # Run main function
275210main
0 commit comments