diff --git a/README.md b/README.md index befd001..d9a0745 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ Bash (debian) script for setting up nginx with docker. # basic commands The script must be ran with root previliges.\ -The script needs a username and a domain name specified using `-u` and `-d` options +The script needs a username specified using `-u` option. \ +After the script is installed you can run it from any directory using `sudo ndss` instead of `sudo ./setup.sh`. ### Add static file server `sudo ./setup.sh -u user -d example.com` ### Add proxy server @@ -28,6 +29,15 @@ This script will then be avaible by calling `ndss` from the command line ### make a backup of the configuration `sudo ./setup.sh -u user -b` +### udpate nginx / php version +`sudo ./setup.sh -u user --update` + +### shutdown running containers +`sudo ./setup.sh -u user --shutdown` + +### stop containers and remove built images +`sudo ./setup.sh -u user --clean` + # command line arguments |argument|default|description| |:---: | :--: | :---------: | @@ -44,6 +54,9 @@ This script will then be avaible by calling `ndss` from the command line | -l --list | - | list all the configured servers. | | -b --backup | - | creates a gzipped tar file and saves it in the user's home directory | | -i --install | - | install this script to make it more accessible using `ndss` command | +| --update | - | backup the old configuration and update the nginx base images | +| --shutdown | - | shutsdown running containers | +| --clean | - | shutsdown running containers and removes the built images. | # Todo - [x] update readme file (because it's way too fucking old) @@ -58,5 +71,8 @@ This script will then be avaible by calling `ndss` from the command line - [x] add systemd timer for checking certifcate renewals. - [x] make the script installable - [x] add option to easily make compressed backups -- [ ] add the functionality to easily update nginx to latest version. +- [x] add the functionality to easily update nginx to latest version. +- [ ] build release package and update instructions on how to install the script +- [ ] make it easier to add foreign container to the nginx network - [ ] add a check to stop the script if one of the actions requires the container to be already running but it's not +- [ ] clean the directory structure \ No newline at end of file diff --git a/nginx-setup.tar.gz b/nginx-setup.tar.gz deleted file mode 100644 index 5d53a0b..0000000 Binary files a/nginx-setup.tar.gz and /dev/null differ diff --git a/nginx.zip b/nginx.zip deleted file mode 100644 index 0bbcb14..0000000 Binary files a/nginx.zip and /dev/null differ diff --git a/setup.sh b/setup.sh index 9b9945a..a7c3e96 100755 --- a/setup.sh +++ b/setup.sh @@ -94,26 +94,31 @@ create_server_files() { fi } -# create the required nginx image +# create the required nginx images create_images() { - if [[ "$(docker images -q $NGINX_IMG_NAME 2> /dev/null)" == "" ]]; then + if [ ! $1 ]; then echo "[LOG] building nginx image..." docker build -f nginx-dockerfile -t $NGINX_IMG_NAME . 1>/dev/null - fi - if [[ "$(docker images -q anismk/php-fpm 2> /dev/null)" == "" ]]; then echo "[LOG] building php image..." docker build -f php-dockerfile -t anismk/php-fpm . 1>/dev/null + else + echo "[LOG] building nginx image (force pull)..." + docker build --pull -f nginx-dockerfile -t $NGINX_IMG_NAME . 1>/dev/null + echo "[LOG] building php image (force pull)..." + docker build --pull -f php-dockerfile -t anismk/php-fpm . 1>/dev/null + fi } # generate docker compose configuration and start server -start_docker_compose() { +build_config_start_docker_compose() { # export project name to be used by docker compose COMPOSE_PROJECT_NAME='ndss' export COMPOSE_PROJECT_NAME - # if nginx image doesn't exist then build it - create_images + if [[ "$(docker images -q $NGINX_IMG_NAME 2> /dev/null)" == "" || "$(docker images -q anismk/php-fpm 2> /dev/null)" == "" ]]; then + create_images + fi # if the image is already running, then simply reload the configuration if [[ $(docker ps | grep anismk-nginx-server) ]]; then @@ -165,7 +170,7 @@ request_certificate() { parse_cmd_args() { # parse command line arguments OPTIONS=u:p:d:t:s:m:lib - LONGOPTS=user:,path:,domain:,type:,proxiedServer:,delete,enable,disable,ssl,email:,list,install,backup + LONGOPTS=user:,path:,domain:,type:,proxiedServer:,delete,enable,disable,ssl,email:,list,install,backup,update,shutdown,clean ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") if [[ ${PIPESTATUS[0]} -ne 0 ]]; then @@ -244,6 +249,22 @@ parse_cmd_args() { ACTION='backup' shift ;; + --update) + ACTION='update' + shift + ;; + --restore) + ACTION='restore' + shift + ;; + --shutdown) + ACTION='shutdown' + shift + ;; + --clean) + ACTION='clean' + shift + ;; --) shift break @@ -261,7 +282,7 @@ parse_cmd_args() { exit 1 fi - if [[ $ACTION != 'list' && $ACTION != 'install' && $ACTION != 'backup' && -z $SERVER_NAME ]]; then + if [[ $ACTION != 'list' && $ACTION != 'install' && $ACTION != 'backup' && $ACTION != 'update' && $ACTION != 'shutdown' && $ACTION != 'clean' && -z $SERVER_NAME ]]; then echo "Please specify the domain name of the service using the '-d | --domain' option" exit 1 fi @@ -293,6 +314,46 @@ parse_cmd_args() { # echo -e "[CONFIG]\nselected user\t: ${USERNAME}\nroot folder\t: ${NGINX_ROOT_FOLDER}\nnew server name\t: ${SERVER_NAME}\n" } + +# update existing containers +update() { + if [ -f $NGINX_ROOT_FOLDER/docker-compose.yml ]; then + echo -e "!! WARNING !!\nThe server will be unavailable for a short period of time while switching between the old and new instance.\nDo you want to continue [y/n]:" + read -n 1 ans + if [ $ans = 'y' ]; then + # make a backup of the old configuration + echo -e "\nA backup of the old configuration has been made at /home/$USERNAME/nginx-backup.tar.gz.\n You can restore this version by running this script with '--restore' command" + tar -C $NGINX_ROOT_FOLDER -czf /home/$USERNAME/nginx-backup.tar.gz . + + # build the new images + create_images 1 + + # respawn containers + CWD=$(pwd) + cd $NGINX_ROOT_FOLDER + + COMPOSE_PROJECT_NAME='ndss' + export COMPOSE_PROJECT_NAME + + docker-compose down + docker-compose up -d 1>/dev/null # will automatically rebuild images if needed + + if [ ! $? ]; then + echo "[ERROR] Update failed. Images need to be rebuilt manually and servers restored from backup." + cd $CWD + exit 1 + else + echo "Containers have been updated successfully." + fi + + cd $CWD + fi + else + echo "[ERROR] Can't upgrade images, as no previous configuration was found." + exit 1 + fi +} + #################################################### ################### main script #################### #################################################### @@ -305,9 +366,11 @@ fi parse_cmd_args $@ # always check if all required packages are installed +check_packages # and the directory structure exists -# check_packages -check_dirs +if [ $ACTION != 'clean' ]; then + check_dirs +fi # hmmmm pure functions, aren't my thing, that's why the code is a bit of a mess :D case $ACTION in @@ -326,7 +389,7 @@ create) create_server_files ;; esac - if start_docker_compose; then + if build_config_start_docker_compose; then if [ $SSL == true ]; then echo "Waiting for nginx to start..." while ! nc -z 127.0.0.1 80; do @@ -405,4 +468,34 @@ install) backup) tar -C $NGINX_ROOT_FOLDER -czf /home/$USERNAME/nginx-backup.tar.gz . echo "The archive is located at /home/$USERNAME/nginx-backup.tar.gz" + ;; + +update) + update + ;; + +shutdown | clean) + # stop and remove containers + if [ -d $NGINX_ROOT_FOLDER ]; then + echo "[LOG] Shutting down containers..." + CWD=$(pwd) + cd $NGINX_ROOT_FOLDER + COMPOSE_PROJECT_NAME='ndss' + export COMPOSE_PROJECT_NAME + docker-compose down + cd $CWD + fi + # remove images if requested + if [ $ACTION == 'clean' ]; then + if [[ "$(docker images -q $NGINX_IMG_NAME 2> /dev/null)" != "" ]]; then + echo "[LOG] Removing nginx image..." + docker image rm $NGINX_IMG_NAME 1>/dev/null + fi + if [[ "$(docker images -q anismk/php-fpm 2> /dev/null)" != "" ]]; then + echo "[LOG] Removing php-fpm image..." + docker image rm anismk/php-fpm 1>/dev/null + fi + echo "[LOG] All clean." + fi + ;; esac diff --git a/templates/nginx/conf.d/default.conf b/templates/nginx/conf.d/default.conf deleted file mode 100644 index b460be0..0000000 --- a/templates/nginx/conf.d/default.conf +++ /dev/null @@ -1,46 +0,0 @@ -server { - listen 80; - listen [::]:80; - server_name localhost; - - #charset koi8-r; - #access_log /var/log/nginx/host.access.log main; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } - - # proxy the PHP scripts to Apache listening on 127.0.0.1:80 - # - #location ~ \.php$ { - # proxy_pass http://127.0.0.1; - #} - - # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 - # - #location ~ \.php$ { - # root html; - # fastcgi_pass 127.0.0.1:9000; - # fastcgi_index index.php; - # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; - # include fastcgi_params; - #} - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} -} - diff --git a/templates/nginx/fastcgi_params b/templates/nginx/fastcgi_params deleted file mode 100644 index 28decb9..0000000 --- a/templates/nginx/fastcgi_params +++ /dev/null @@ -1,25 +0,0 @@ - -fastcgi_param QUERY_STRING $query_string; -fastcgi_param REQUEST_METHOD $request_method; -fastcgi_param CONTENT_TYPE $content_type; -fastcgi_param CONTENT_LENGTH $content_length; - -fastcgi_param SCRIPT_NAME $fastcgi_script_name; -fastcgi_param REQUEST_URI $request_uri; -fastcgi_param DOCUMENT_URI $document_uri; -fastcgi_param DOCUMENT_ROOT $document_root; -fastcgi_param SERVER_PROTOCOL $server_protocol; -fastcgi_param REQUEST_SCHEME $scheme; -fastcgi_param HTTPS $https if_not_empty; - -fastcgi_param GATEWAY_INTERFACE CGI/1.1; -fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; - -fastcgi_param REMOTE_ADDR $remote_addr; -fastcgi_param REMOTE_PORT $remote_port; -fastcgi_param SERVER_ADDR $server_addr; -fastcgi_param SERVER_PORT $server_port; -fastcgi_param SERVER_NAME $server_name; - -# PHP only, required if PHP was built with --enable-force-cgi-redirect -fastcgi_param REDIRECT_STATUS 200; diff --git a/templates/nginx/koi-utf b/templates/nginx/koi-utf deleted file mode 100644 index e7974ff..0000000 --- a/templates/nginx/koi-utf +++ /dev/null @@ -1,109 +0,0 @@ - -# This map is not a full koi8-r <> utf8 map: it does not contain -# box-drawing and some other characters. Besides this map contains -# several koi8-u and Byelorussian letters which are not in koi8-r. -# If you need a full and standard map, use contrib/unicode2nginx/koi-utf -# map instead. - -charset_map koi8-r utf-8 { - - 80 E282AC ; # euro - - 95 E280A2 ; # bullet - - 9A C2A0 ; #   - - 9E C2B7 ; # · - - A3 D191 ; # small yo - A4 D194 ; # small Ukrainian ye - - A6 D196 ; # small Ukrainian i - A7 D197 ; # small Ukrainian yi - - AD D291 ; # small Ukrainian soft g - AE D19E ; # small Byelorussian short u - - B0 C2B0 ; # ° - - B3 D081 ; # capital YO - B4 D084 ; # capital Ukrainian YE - - B6 D086 ; # capital Ukrainian I - B7 D087 ; # capital Ukrainian YI - - B9 E28496 ; # numero sign - - BD D290 ; # capital Ukrainian soft G - BE D18E ; # capital Byelorussian short U - - BF C2A9 ; # (C) - - C0 D18E ; # small yu - C1 D0B0 ; # small a - C2 D0B1 ; # small b - C3 D186 ; # small ts - C4 D0B4 ; # small d - C5 D0B5 ; # small ye - C6 D184 ; # small f - C7 D0B3 ; # small g - C8 D185 ; # small kh - C9 D0B8 ; # small i - CA D0B9 ; # small j - CB D0BA ; # small k - CC D0BB ; # small l - CD D0BC ; # small m - CE D0BD ; # small n - CF D0BE ; # small o - - D0 D0BF ; # small p - D1 D18F ; # small ya - D2 D180 ; # small r - D3 D181 ; # small s - D4 D182 ; # small t - D5 D183 ; # small u - D6 D0B6 ; # small zh - D7 D0B2 ; # small v - D8 D18C ; # small soft sign - D9 D18B ; # small y - DA D0B7 ; # small z - DB D188 ; # small sh - DC D18D ; # small e - DD D189 ; # small shch - DE D187 ; # small ch - DF D18A ; # small hard sign - - E0 D0AE ; # capital YU - E1 D090 ; # capital A - E2 D091 ; # capital B - E3 D0A6 ; # capital TS - E4 D094 ; # capital D - E5 D095 ; # capital YE - E6 D0A4 ; # capital F - E7 D093 ; # capital G - E8 D0A5 ; # capital KH - E9 D098 ; # capital I - EA D099 ; # capital J - EB D09A ; # capital K - EC D09B ; # capital L - ED D09C ; # capital M - EE D09D ; # capital N - EF D09E ; # capital O - - F0 D09F ; # capital P - F1 D0AF ; # capital YA - F2 D0A0 ; # capital R - F3 D0A1 ; # capital S - F4 D0A2 ; # capital T - F5 D0A3 ; # capital U - F6 D096 ; # capital ZH - F7 D092 ; # capital V - F8 D0AC ; # capital soft sign - F9 D0AB ; # capital Y - FA D097 ; # capital Z - FB D0A8 ; # capital SH - FC D0AD ; # capital E - FD D0A9 ; # capital SHCH - FE D0A7 ; # capital CH - FF D0AA ; # capital hard sign -} diff --git a/templates/nginx/koi-win b/templates/nginx/koi-win deleted file mode 100644 index 72afabe..0000000 --- a/templates/nginx/koi-win +++ /dev/null @@ -1,103 +0,0 @@ - -charset_map koi8-r windows-1251 { - - 80 88 ; # euro - - 95 95 ; # bullet - - 9A A0 ; #   - - 9E B7 ; # · - - A3 B8 ; # small yo - A4 BA ; # small Ukrainian ye - - A6 B3 ; # small Ukrainian i - A7 BF ; # small Ukrainian yi - - AD B4 ; # small Ukrainian soft g - AE A2 ; # small Byelorussian short u - - B0 B0 ; # ° - - B3 A8 ; # capital YO - B4 AA ; # capital Ukrainian YE - - B6 B2 ; # capital Ukrainian I - B7 AF ; # capital Ukrainian YI - - B9 B9 ; # numero sign - - BD A5 ; # capital Ukrainian soft G - BE A1 ; # capital Byelorussian short U - - BF A9 ; # (C) - - C0 FE ; # small yu - C1 E0 ; # small a - C2 E1 ; # small b - C3 F6 ; # small ts - C4 E4 ; # small d - C5 E5 ; # small ye - C6 F4 ; # small f - C7 E3 ; # small g - C8 F5 ; # small kh - C9 E8 ; # small i - CA E9 ; # small j - CB EA ; # small k - CC EB ; # small l - CD EC ; # small m - CE ED ; # small n - CF EE ; # small o - - D0 EF ; # small p - D1 FF ; # small ya - D2 F0 ; # small r - D3 F1 ; # small s - D4 F2 ; # small t - D5 F3 ; # small u - D6 E6 ; # small zh - D7 E2 ; # small v - D8 FC ; # small soft sign - D9 FB ; # small y - DA E7 ; # small z - DB F8 ; # small sh - DC FD ; # small e - DD F9 ; # small shch - DE F7 ; # small ch - DF FA ; # small hard sign - - E0 DE ; # capital YU - E1 C0 ; # capital A - E2 C1 ; # capital B - E3 D6 ; # capital TS - E4 C4 ; # capital D - E5 C5 ; # capital YE - E6 D4 ; # capital F - E7 C3 ; # capital G - E8 D5 ; # capital KH - E9 C8 ; # capital I - EA C9 ; # capital J - EB CA ; # capital K - EC CB ; # capital L - ED CC ; # capital M - EE CD ; # capital N - EF CE ; # capital O - - F0 CF ; # capital P - F1 DF ; # capital YA - F2 D0 ; # capital R - F3 D1 ; # capital S - F4 D2 ; # capital T - F5 D3 ; # capital U - F6 C6 ; # capital ZH - F7 C2 ; # capital V - F8 DC ; # capital soft sign - F9 DB ; # capital Y - FA C7 ; # capital Z - FB D8 ; # capital SH - FC DD ; # capital E - FD D9 ; # capital SHCH - FE D7 ; # capital CH - FF DA ; # capital hard sign -} diff --git a/templates/nginx/mime.types b/templates/nginx/mime.types deleted file mode 100644 index 2961256..0000000 --- a/templates/nginx/mime.types +++ /dev/null @@ -1,97 +0,0 @@ - -types { - text/html html htm shtml; - text/css css; - text/xml xml; - image/gif gif; - image/jpeg jpeg jpg; - application/javascript js; - application/atom+xml atom; - application/rss+xml rss; - - text/mathml mml; - text/plain txt; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/x-component htc; - - image/png png; - image/svg+xml svg svgz; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/webp webp; - image/x-icon ico; - image/x-jng jng; - image/x-ms-bmp bmp; - - font/woff woff; - font/woff2 woff2; - - application/java-archive jar war ear; - application/json json; - application/mac-binhex40 hqx; - application/msword doc; - application/pdf pdf; - application/postscript ps eps ai; - application/rtf rtf; - application/vnd.apple.mpegurl m3u8; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/vnd.ms-excel xls; - application/vnd.ms-fontobject eot; - application/vnd.ms-powerpoint ppt; - application/vnd.oasis.opendocument.graphics odg; - application/vnd.oasis.opendocument.presentation odp; - application/vnd.oasis.opendocument.spreadsheet ods; - application/vnd.oasis.opendocument.text odt; - application/vnd.openxmlformats-officedocument.presentationml.presentation - pptx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - xlsx; - application/vnd.openxmlformats-officedocument.wordprocessingml.document - docx; - application/vnd.wap.wmlc wmlc; - application/x-7z-compressed 7z; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-perl pl pm; - application/x-pilot prc pdb; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert der pem crt; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xspf+xml xspf; - application/zip zip; - - application/octet-stream bin exe dll; - application/octet-stream deb; - application/octet-stream dmg; - application/octet-stream iso img; - application/octet-stream msi msp msm; - - audio/midi mid midi kar; - audio/mpeg mp3; - audio/ogg ogg; - audio/x-m4a m4a; - audio/x-realaudio ra; - - video/3gpp 3gpp 3gp; - video/mp2t ts; - video/mp4 mp4; - video/mpeg mpeg mpg; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-m4v m4v; - video/x-mng mng; - video/x-ms-asf asx asf; - video/x-ms-wmv wmv; - video/x-msvideo avi; -} diff --git a/templates/nginx/nginx.conf b/templates/nginx/nginx.conf deleted file mode 100644 index e4bad8d..0000000 --- a/templates/nginx/nginx.conf +++ /dev/null @@ -1,32 +0,0 @@ - -user nginx; -worker_processes 1; - -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; - - -events { - worker_connections 1024; -} - - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - include /etc/nginx/conf.d/*.conf; -} diff --git a/templates/nginx/scgi_params b/templates/nginx/scgi_params deleted file mode 100644 index 6d4ce4f..0000000 --- a/templates/nginx/scgi_params +++ /dev/null @@ -1,17 +0,0 @@ - -scgi_param REQUEST_METHOD $request_method; -scgi_param REQUEST_URI $request_uri; -scgi_param QUERY_STRING $query_string; -scgi_param CONTENT_TYPE $content_type; - -scgi_param DOCUMENT_URI $document_uri; -scgi_param DOCUMENT_ROOT $document_root; -scgi_param SCGI 1; -scgi_param SERVER_PROTOCOL $server_protocol; -scgi_param REQUEST_SCHEME $scheme; -scgi_param HTTPS $https if_not_empty; - -scgi_param REMOTE_ADDR $remote_addr; -scgi_param REMOTE_PORT $remote_port; -scgi_param SERVER_PORT $server_port; -scgi_param SERVER_NAME $server_name; diff --git a/templates/nginx/uwsgi_params b/templates/nginx/uwsgi_params deleted file mode 100644 index 09c732c..0000000 --- a/templates/nginx/uwsgi_params +++ /dev/null @@ -1,17 +0,0 @@ - -uwsgi_param QUERY_STRING $query_string; -uwsgi_param REQUEST_METHOD $request_method; -uwsgi_param CONTENT_TYPE $content_type; -uwsgi_param CONTENT_LENGTH $content_length; - -uwsgi_param REQUEST_URI $request_uri; -uwsgi_param PATH_INFO $document_uri; -uwsgi_param DOCUMENT_ROOT $document_root; -uwsgi_param SERVER_PROTOCOL $server_protocol; -uwsgi_param REQUEST_SCHEME $scheme; -uwsgi_param HTTPS $https if_not_empty; - -uwsgi_param REMOTE_ADDR $remote_addr; -uwsgi_param REMOTE_PORT $remote_port; -uwsgi_param SERVER_PORT $server_port; -uwsgi_param SERVER_NAME $server_name; diff --git a/templates/nginx/win-utf b/templates/nginx/win-utf deleted file mode 100644 index ed8bc00..0000000 --- a/templates/nginx/win-utf +++ /dev/null @@ -1,126 +0,0 @@ - -# This map is not a full windows-1251 <> utf8 map: it does not -# contain Serbian and Macedonian letters. If you need a full map, -# use contrib/unicode2nginx/win-utf map instead. - -charset_map windows-1251 utf-8 { - - 82 E2809A ; # single low-9 quotation mark - - 84 E2809E ; # double low-9 quotation mark - 85 E280A6 ; # ellipsis - 86 E280A0 ; # dagger - 87 E280A1 ; # double dagger - 88 E282AC ; # euro - 89 E280B0 ; # per mille - - 91 E28098 ; # left single quotation mark - 92 E28099 ; # right single quotation mark - 93 E2809C ; # left double quotation mark - 94 E2809D ; # right double quotation mark - 95 E280A2 ; # bullet - 96 E28093 ; # en dash - 97 E28094 ; # em dash - - 99 E284A2 ; # trade mark sign - - A0 C2A0 ; #   - A1 D18E ; # capital Byelorussian short U - A2 D19E ; # small Byelorussian short u - - A4 C2A4 ; # currency sign - A5 D290 ; # capital Ukrainian soft G - A6 C2A6 ; # borken bar - A7 C2A7 ; # section sign - A8 D081 ; # capital YO - A9 C2A9 ; # (C) - AA D084 ; # capital Ukrainian YE - AB C2AB ; # left-pointing double angle quotation mark - AC C2AC ; # not sign - AD C2AD ; # soft hypen - AE C2AE ; # (R) - AF D087 ; # capital Ukrainian YI - - B0 C2B0 ; # ° - B1 C2B1 ; # plus-minus sign - B2 D086 ; # capital Ukrainian I - B3 D196 ; # small Ukrainian i - B4 D291 ; # small Ukrainian soft g - B5 C2B5 ; # micro sign - B6 C2B6 ; # pilcrow sign - B7 C2B7 ; # · - B8 D191 ; # small yo - B9 E28496 ; # numero sign - BA D194 ; # small Ukrainian ye - BB C2BB ; # right-pointing double angle quotation mark - - BF D197 ; # small Ukrainian yi - - C0 D090 ; # capital A - C1 D091 ; # capital B - C2 D092 ; # capital V - C3 D093 ; # capital G - C4 D094 ; # capital D - C5 D095 ; # capital YE - C6 D096 ; # capital ZH - C7 D097 ; # capital Z - C8 D098 ; # capital I - C9 D099 ; # capital J - CA D09A ; # capital K - CB D09B ; # capital L - CC D09C ; # capital M - CD D09D ; # capital N - CE D09E ; # capital O - CF D09F ; # capital P - - D0 D0A0 ; # capital R - D1 D0A1 ; # capital S - D2 D0A2 ; # capital T - D3 D0A3 ; # capital U - D4 D0A4 ; # capital F - D5 D0A5 ; # capital KH - D6 D0A6 ; # capital TS - D7 D0A7 ; # capital CH - D8 D0A8 ; # capital SH - D9 D0A9 ; # capital SHCH - DA D0AA ; # capital hard sign - DB D0AB ; # capital Y - DC D0AC ; # capital soft sign - DD D0AD ; # capital E - DE D0AE ; # capital YU - DF D0AF ; # capital YA - - E0 D0B0 ; # small a - E1 D0B1 ; # small b - E2 D0B2 ; # small v - E3 D0B3 ; # small g - E4 D0B4 ; # small d - E5 D0B5 ; # small ye - E6 D0B6 ; # small zh - E7 D0B7 ; # small z - E8 D0B8 ; # small i - E9 D0B9 ; # small j - EA D0BA ; # small k - EB D0BB ; # small l - EC D0BC ; # small m - ED D0BD ; # small n - EE D0BE ; # small o - EF D0BF ; # small p - - F0 D180 ; # small r - F1 D181 ; # small s - F2 D182 ; # small t - F3 D183 ; # small u - F4 D184 ; # small f - F5 D185 ; # small kh - F6 D186 ; # small ts - F7 D187 ; # small ch - F8 D188 ; # small sh - F9 D189 ; # small shch - FA D18A ; # small hard sign - FB D18B ; # small y - FC D18C ; # small soft sign - FD D18D ; # small e - FE D18E ; # small yu - FF D18F ; # small ya -}