├── .gitignore ├── LICENSE ├── README.md ├── VERSION └── ng /.gitignore: -------------------------------------------------------------------------------- 1 | ng.bak -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Patrick Curl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Support Me by going to my Etsy store : http://myjarofhope.etsy.com 2 | =========== 3 | Bash Script to allow create or delete nginx virtual hosts on linux in a quick way. 4 | 5 | ## Installation ## 6 | 7 | ```shell 8 | $ mkdir ~/bin && cd ~/bin 9 | $ git clone https://github.com/patrickcurl/ngtool 10 | $ cd ngtool && chmod +x ng 11 | $ sudo ln -s /home/username/bin/ngtool/ng /usr/local/bin/ng 12 | ``` 13 | 14 | Alternately you can add the ngtool directory to your $PATH, it just needs to be in a folder that's in the $PATH. 15 | 16 | I also recommend adding an alias to ~/.bash_rc or ~/.bash_aliases : alias ng="sudo ng" 17 | 18 | The script requires being run as sudo, or else you can't modify nginx files - this way it'll do so by default, and you 19 | still need to enter a password. 20 | 21 | ## Caveat Emptor on .dev domains and HSTS ## 22 | 23 | '.dev' domains are blocked from browsers now because of HSTS (blame google), I highly recommend only using '.test'. 24 | 25 | On my system what I've done is enabled a global dns wildcard using dnsmasq, this makes it so all .test domains are local and need no editing. 26 | 27 | I'm on ARCH linux so YMMV, but to do this I added a file named test.tld in /etc/NetworkManager/dnsmasq.d with the following contents: 28 | 29 | ``` 30 | local=/test/ 31 | address=/test/127.0.0.1 32 | listen-address=127.0.0.1 33 | ``` 34 | 35 | Then run: 36 | ```shell 37 | $ sudo systemctl restart NetworkManager 38 | $ ping anything.test 39 | ``` 40 | 41 | You'll need to wait for the Network Manager to start back up in a few seconds before running the ping, but any domain should now resolve locally without editing hosts file. 42 | 43 | Now you can edit the useHosts config in the NG tool to false as you won't need to edit hosts. 44 | 45 | 46 | ## Config ## 47 | ```bash 48 | ### CONFIG SETTINGS 49 | # Put owner/group that nginx must run under for your system. 50 | # The default on ubuntu would be user: www-data group: www-data. 51 | # This is my personal settings for Arch linux. 52 | 53 | #owner for chowing -- this is the owner nginx uses. 54 | owner=patrick 55 | 56 | #group for chowing -- this is the group nginx uses. 57 | group=users 58 | 59 | #sites-enabled path 60 | sitesEnabled='/etc/nginx/sites-enabled/' 61 | 62 | #sites-available path 63 | sitesAvailable='/etc/nginx/sites-available/' 64 | 65 | #make true if you do not have a global .test wildcard setup via dnsmasq or other. 66 | useHosts=false 67 | 68 | #whether to use, setup and regenerate self-signed wildcard ssl. 69 | useSSL=true 70 | 71 | # SSL Settings only matter if useSSL is true. 72 | sslConfig='/etc/nginx/ssl/ssl_servers.cfg' 73 | sslKey='/etc/nginx/ssl/nginx.key' 74 | sslCert='/etc/nginx/ssl/nginx.crt' 75 | 76 | # Change this to match what your system uses. 77 | #arch 78 | restart='systemctl restart nginx' 79 | 80 | #ubuntu 81 | # restart=service nginx restart 82 | 83 | ### END CONFIG SETTINGS 84 | ``` 85 | 86 | ## Usage ## 87 | 88 | Basic command line syntax: 89 | 90 | ```bash 91 | $ ng [create | delete | enable | disable] [domain] [/full/path/to/project/dir] 92 | ``` 93 | 94 | ### Examples ### 95 | 96 | To create a new virtual host: 97 | 98 | ```bash 99 | $ ng create mysite.test /home/patrick/projects/laravel/mysite/public 100 | ``` 101 | To delete a virtual host 102 | 103 | ```bash 104 | $ ng delete mysite.dev 105 | ``` 106 | 107 | To enable ALL virtual hosts: 108 | 109 | ```bash 110 | $ ng enable 111 | ``` 112 | 113 | To enable a single virtual host: 114 | 115 | ```bash 116 | $ ng enable vhost.test 117 | ``` 118 | To disable all hosts: 119 | 120 | ```bash 121 | $ ng disable all 122 | ``` 123 | 124 | To disable a single host: 125 | 126 | ```bash 127 | $ ng disable vhost.test 128 | ``` 129 | 130 | ## License ## 131 | MIT : Basically do whatever just provide copyright notice w/ all derivatives. 132 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.0.9 -------------------------------------------------------------------------------- /ng: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # MIT License 3 | 4 | # Copyright (c) 2017 Patrick Curl | SoaringHost 5 | # https://github.com/patrickcurl/ngTool 6 | 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | ### Set Language 26 | TEXTDOMAIN=virtualhost 27 | 28 | ### Set default parameters 29 | action=$1 30 | domain=$2 31 | root=$3 32 | 33 | ### CONFIG SETTINGS 34 | # Put owner/group that nginx must run under for your system. 35 | # The default on ubuntu would be user: www-data group: www-data. 36 | # This is my personal settings for Arch linux. 37 | owner=patrick #owner for chmoding -- this is the owner nginx uses. 38 | group=users #group for chmoding -- this is the group nginx uses. 39 | sitesEnabled='/etc/nginx/sites-enabled/' #sites-enabled path 40 | sitesAvailable='/etc/nginx/sites-available/' #sites-available path 41 | useHosts=false # make true if you do not have a global .test wildcard setup via dnsmasq or other. 42 | useSSL=true 43 | sslConfig='/etc/nginx/ssl/ssl_servers.cfg' 44 | sslKey='/etc/nginx/ssl/nginx.key' 45 | sslCert='/etc/nginx/ssl/nginx.crt' 46 | # Change this to match what your system uses. 47 | #arch 48 | restart='systemctl restart nginx' 49 | #ubuntu 50 | # restart=service nginx restart 51 | ### END CONFIG SETTINGS 52 | 53 | function regenerate_ssls { 54 | echo $sitesAvailable 55 | # sitesAvailable = $1 56 | # sslConfig = $2 57 | # sslKey = $3 58 | # sslCert = $4 59 | SSL_DOMAINS=`sed -n -e 's/^.*server_name //p' $sitesAvailable* | tr " " "\n" | sed '/^\s*$/d' | cut -d ';' -f1 | sort -u` 60 | cat < $sslConfig 61 | [ req ] 62 | req_extensions = req_ext 63 | distinguished_name = req_distinguished_name 64 | prompt = no 65 | 66 | [req_distinguished_name] 67 | commonName=localhost.test 68 | 69 | [req_ext] 70 | subjectAltName = @alt_names 71 | 72 | [alt_names] 73 | EOT 74 | count=1; 75 | for SDOMAIN in $SSL_DOMAINS; do 76 | if [ "$SDOMAIN" != '_' ]; then 77 | let count++; 78 | dns="DNS.$count = $SDOMAIN"; 79 | echo $dns >> $sslConfig; 80 | fi 81 | done 82 | `sudo openssl req -x509 -config $sslConfig -extensions req_ext -nodes -days 730 -newkey rsa:2048 -sha256 -keyout $sslKey -out $sslCert` 83 | } 84 | 85 | function restart_nginx { 86 | $restart 87 | echo -e $"Nginx restarted!" 88 | } 89 | 90 | function version { 91 | echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; 92 | } 93 | 94 | function check_version { 95 | echo -e "Checking for updates.\n"; 96 | SCRIPT="$(readlink --canonicalize-existing "$0")" 97 | SCRIPT_PATH="$(dirname $SCRIPT)" 98 | CURRENT_VERSION=`cat $SCRIPT_PATH/VERSION` 99 | NEW_VERSION="`wget -qO- https://raw.githubusercontent.com/patrickcurl/ngtool/master/VERSION`" 100 | 101 | if [ $CURRENT_VERSION != "" ] && [ $(version $CURRENT_VERSION) -lt $(version $NEW_VERSION) ]; then 102 | echo -e $"There is an update available (Current: $CURRENT_VERSION | New: $NEW_VERSION) to update do the following:\n" 103 | echo -e $"cd $SCRIPT_PATH && git pull origin master\n" 104 | else 105 | echo -e $"You already have the latest version"; 106 | fi 107 | } 108 | 109 | if [ "$(whoami)" != 'root' ]; then 110 | echo $"You have no permission to run \ 111 | $0 as non-root user. Use sudo" 112 | exit 1; 113 | fi 114 | 115 | check_version 116 | 117 | if [ "$action" != "create" ] && [ "$action" != "delete" ] \ 118 | && [ "$action" != "enable" ] && [ "$action" != "disable" ]; then 119 | echo $"You need to prompt for action \ 120 | (create, delete or enable or disable) -- Lower-case only" 121 | exit; 122 | fi 123 | 124 | while [ "$domain" == "" ]; do 125 | if [ "$action" == "create" ] || [ "$action" == "delete" ]; then 126 | echo -e $"Please provide domain. e.g. mysite.dev" 127 | read domain 128 | else 129 | break 130 | fi 131 | done 132 | 133 | ### if root dir starts with '/', don't use /var/www as default starting point 134 | if [ "$action" == "create" ]; then 135 | echo -e $"Creating $domain...\n" 136 | while [ "$root" == "" ]; do 137 | echo -e $"Please provide a full directory e.g. /home/user/projects/myproject/public" 138 | read root 139 | done 140 | ### check if domain already exists 141 | if [ -e $sitesAvailable$domain ]; then 142 | echo -e $"This domain already exists.\nPlease Try Another one" 143 | exit; 144 | fi 145 | 146 | ### check if directory exists or not 147 | if ! [ -d $root ]; then 148 | ### create the directory 149 | mkdir $root 150 | ### give permission to root dir 151 | chmod 755 root 152 | ### write test file in the new domain dir 153 | if ! echo "" > $root/phpinfo.php 154 | then 155 | echo $"ERROR: Not able to write in file $root/phpinfo.php. Please check permissions." 156 | exit; 157 | else 158 | echo $"Added content to $root/phpinfo.php." 159 | fi 160 | fi 161 | ### create virtual host rules file 162 | if ! echo "server { 163 | listen 80; 164 | listen [::]:80; 165 | listen 443 ssl http2; 166 | listen [::]:443 ssl http2; 167 | root $root; 168 | index index.php index.html index.htm; 169 | server_name $domain; 170 | 171 | ssl_certificate $sslCert; 172 | ssl_certificate_key $sslKey; 173 | 174 | # serve static files directly 175 | location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)\$ { 176 | access_log off; 177 | expires max; 178 | } 179 | 180 | 181 | # catch all 182 | error_page 404 /index.php; 183 | 184 | location / { 185 | 186 | try_files \$uri \$uri/ /index.php?\$query_string; 187 | 188 | # A bunch of perm page redirects from my old 189 | # site structure for SEO purposes. Not interesting. 190 | 191 | # include /etc/nginx/templates/redirects; 192 | 193 | } 194 | 195 | if (!-d \$request_filename) { 196 | rewrite ^/(.+)/\$ /\$1 permanent; 197 | } 198 | 199 | 200 | location ~* \.php\$ { 201 | try_files \$uri /index.php =404; 202 | # Server PHP config. 203 | fastcgi_pass unix:/run/php-fpm/php-fpm.sock; 204 | fastcgi_index index.php; 205 | fastcgi_split_path_info ^(.+\.php)(/.+)\$; 206 | 207 | # Typical vars in here, nothing interesting. 208 | 209 | include /etc/nginx/fastcgi_params; 210 | fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; 211 | 212 | } 213 | 214 | location ~ /\.ht { 215 | 216 | # Hells no, we usin nginx up in this mutha. (deny .htaccess) 217 | deny all; 218 | 219 | } 220 | 221 | }" > $sitesAvailable$domain 222 | then 223 | echo -e $"There is an ERROR create $domain file" 224 | exit; 225 | else 226 | echo -e $"\nNew Virtual Host Created\n" 227 | fi 228 | if [ "$useHosts" == true ]; then 229 | ### Add domain in /etc/hosts 230 | if ! echo "127.0.0.1 $domain" >> /etc/hosts 231 | then 232 | echo $"ERROR: Not able write in /etc/hosts" 233 | exit; 234 | else 235 | echo -e $"Host added to /etc/hosts file \n" 236 | fi 237 | fi 238 | chown -R $owner:$group $root 239 | ### enable website 240 | ln -s $sitesAvailable$domain $sitesEnabled$domain 241 | 242 | ### SETUP SSLS for all existing domains. 243 | 244 | ### restart Nginx 245 | if [ "$useSSL" == true ]; then 246 | regenerate_ssls $sitesAvailable $sslConfig $sslKey $sslCert 247 | fi 248 | 249 | restart_nginx 250 | 251 | ### show the finished message 252 | echo -e $"Complete! \nYou now have a new Virtual Host \nYour new host is: http://$domain \nAnd its located at $root" 253 | exit; 254 | fi 255 | 256 | if [ "$action" == "delete" ]; then 257 | echo -e $"Deleting $domain...\n" 258 | ### check whether domain already exists 259 | if ! [ -e $sitesAvailable$domain ]; then 260 | echo -e $"This domain does not exists.\nPlease Try Another one" 261 | exit; 262 | else 263 | if [ "$useHosts" == true ]; then 264 | ### Delete domain in /etc/hosts 265 | newhost=${domain//./\\.} 266 | sed -i "/$newhost/d" /etc/hosts 267 | fi 268 | ### disable website 269 | rm $sitesEnabled$domain 270 | 271 | ### restart Nginx 272 | #service nginx restart 273 | restart_nginx 274 | ### Delete virtual host rules files 275 | rm $sitesAvailable$domain 276 | echo -e $"Complete!\nYou just removed Virtual Host $domain. \nThe root folder still exists. You'll need to manually delete it." 277 | exit; 278 | fi 279 | fi 280 | 281 | if [ "$action" == "enable" ]; then 282 | if [ "$domain" == "" ]; then 283 | echo -e $"No domain supplied, re-enabling all domains"; 284 | FILES=$sitesAvailable* 285 | for f in $FILES; do 286 | file=`basename $f`; 287 | if ! [ -f "$sitesEnabled$file" ]; then 288 | echo -e $"Enabling: $file" 289 | `sudo ln -s $sitesAvailable$file $sitesEnabled$file` 290 | fi 291 | done 292 | restart_nginx 293 | echo -e $"Complete! ALL Nginx sites are now enabled. Happy coding!" 294 | exit; 295 | else 296 | echo -e $"Enabling $domain...\n" 297 | if ! [ -f "$sitesAvailable$domain" ]; then 298 | echo -e $"Domain file missing from $sitesAvailable, please add it then try again." 299 | exit; 300 | fi 301 | if [ -f "$sitesEnabled$domain" ]; then 302 | echo -e $"Domain is already enabled, no need to renable." 303 | exit; 304 | else 305 | `sudo ln -s $sitesAvailable$domain $sitesEnabled$domain` 306 | echo -e $"Domain $domain has been enabled. Happy coding!" 307 | restart_nginx 308 | exit; 309 | fi 310 | fi 311 | fi 312 | 313 | if [ "$action" == "disable" ]; then 314 | echo -e $"Disabling $domain...\n" 315 | if [ "$domain" == "" ]; then 316 | echo -e $"No domain supplied, disabling requires a domain! \nIf you really want to disable ALL domains then try: ng disable all" 317 | exit; 318 | fi 319 | 320 | if [ "$domain" == "all" ]; then 321 | FILES=$sitesEnabled* 322 | for f in $FILES; do 323 | file=`basename $f` 324 | if [ -f "$f" ]; then 325 | `rm -rf $f` 326 | if [ -f "$f" ]; then 327 | echo -e $"Error: $file was unable to be disabled" 328 | else 329 | echo -e $"$file as been disabled successfully." 330 | fi 331 | else 332 | echo -e $"File does not exist, skipping" 333 | fi 334 | done 335 | restart_nginx 336 | fi 337 | if [ "$domain" != "all" ] && [ "$domain" != "" ]; then 338 | file="$sitesEnabled$domain" 339 | if [ -f "$file" ]; then 340 | `rm -rf $file` 341 | if ! [ -f "$file" ]; then 342 | echo -e $"Site $domain has been disabled!" 343 | else 344 | echo -e $"Something went wrong, unable to disable site!" 345 | fi 346 | else 347 | echo -e $"File does not exist. Did you spell it right?" 348 | fi 349 | restart_nginx 350 | fi 351 | fi 352 | --------------------------------------------------------------------------------