├── 0x00-shell_basics ├── 0-current_working_directory ├── 1-listit ├── 10-back ├── 100-lets_move ├── 101-clean_emacs ├── 102-tree ├── 103-commas ├── 11-lists ├── 12-file_type ├── 13-symbolic_link ├── 14-copy_html ├── 2-bring_me_home ├── 3-listfiles ├── 4-listmorefiles ├── 5-listfilesdigitonly ├── 6-firstdirectory ├── 7-movethatfile ├── 8-firstdelete ├── 9-firstdirdeletion ├── README.md ├── __ls__ └── school.mgc ├── 0x01-shell_permissions ├── 0-iam_betty ├── 1-who_am_i ├── 10-mirror_permissions ├── 100-change_owner_and_group ├── 101-symbolic_link_permissions ├── 102-if_only ├── 103-Star_Wars ├── 11-directories_permissions ├── 12-directory_permissions ├── 13-change_group ├── 2-groups ├── 3-new_owner ├── 4-empty ├── 5-execute ├── 6-multiple_permissions ├── 7-everybody ├── 8-James_Bond ├── 9-John_Doe └── README.md ├── 0x02-shell_redirections ├── 208 ├── 0-hello_world ├── 1-confused_smiley ├── 10-no_more_js ├── 100-empty_casks ├── 101-gifs ├── 102-acrostic ├── 103-the_biggest_fan ├── 11-directories ├── 12-newest_files ├── 13-unique ├── 14-findthatword ├── 15-countthatword ├── 16-whatsnext ├── 17-hidethisword ├── 18-letteronly ├── 19-AZ ├── 2-hellofile ├── 20-hiago ├── 21-reverse ├── 22-users_and_homes ├── 3-twofiles ├── 4-lastlines ├── 5-firstlines ├── 6-third_line ├── 7-file ├── 8-cwd_state ├── 9-duplicate_last_line ├── README.md ├── \*\\'"Best School"\'\\*$\?\*\*\*\*\*:) ├── iacta └── ls_cwd_content ├── 0x03-shell_variables_expansions ├── .4-global_variables.swp ├── 0-alias ├── 1-hello_you ├── 10-love_exponent_breath ├── 100-decimal_to_hexadecimal ├── 101-rot13 ├── 102-odd ├── 103-water_and_stir ├── 11-binary_to_decimal ├── 12-combinations ├── 13-print_float ├── 2-path ├── 3-paths ├── 4-global_variables ├── 5-local_variables ├── 6-create_local_variable ├── 7-create_global_variable ├── 8-true_knowledge ├── 9-divide_and_rule ├── README.md └── quote ├── 0x04-loops_conditions_and_parsing ├── .101-tell_the_story_of_passwd.swp ├── 0-RSA_public_key.pub ├── 1-for_best_school ├── 10-fizzbuzz ├── 100-read_and_cut ├── 101-tell_the_story_of_passwd ├── 102-lets_parse_apache_logs ├── 103-dig_the-data ├── 2-while_best_school ├── 3-until_best_school ├── 4-if_9_say_hi ├── 5-4_bad_luck_8_is_your_chance ├── 6-superstitious_numbers ├── 7-clock ├── 8-for_ls ├── 9-to_file_or_not_to_file └── README.md ├── 0x05-processes_and_signals ├── 0-what-is-my-pid ├── 1-list_your_processes ├── 100-process_and_pid_file ├── 101-manage_my_process ├── 101-manage_my_process, ├── 102-zombie.c ├── 2-show_your_bash_pid ├── 3-show_your_bash_pid_made_easy ├── 4-to_infinity_and_beyond ├── 5-dont_stop_me_now ├── 6-stop_me_if_you_can ├── 7-highlander ├── 8-beheaded_process ├── README.md └── manage_my_process ├── 0x06-regular_expressions ├── 0-simply_match_school.rb ├── 1-repetition_token_0.rb ├── 100-textme.rb ├── 2-repetition_token_1.rb ├── 3-repetition_token_2.rb ├── 4-repetition_token_3.rb ├── 5-beginning_and_end.rb ├── 6-phone_number.rb ├── 7-OMG_WHY_ARE_YOU_SHOUTING.rb └── README.md ├── 0x07-networking_basics ├── 0-OSI_model ├── 1-types_of_network ├── 2-MAC_and_IP_address ├── 3-UDP_and_TCP ├── 4-TCP_and_UDP_ports ├── 5-is_the_host_on_the_network └── README.md ├── 0x08-networking_basics_2 ├── 0-change_your_home_IP ├── 1-show_attached_IPs ├── 100-port_listening_on_localhost └── README.md ├── 0x09-web_infrastructure_design ├── 0-simple_web_stack ├── 1-distributed_web_infrastructure ├── 2-secured_and_monitored_web_infrastructure ├── 3-scale_up └── README.md ├── 0x0A-configuration_management ├── 0-create_a_file.pp ├── 1-install_a_package.pp ├── 2-execute_a_command.pp └── README.md ├── 0x0B-ssh ├── 0-use_a_private_key ├── 1-create_ssh_key_pair ├── 100-puppet_ssh_config.pp ├── 2-ssh_config └── README.md ├── 0x0C-web_server ├── .0-transfer_file.swp ├── .2-setup_a_domain_name.swo ├── .README.md.swp ├── 0-transfer_file ├── 1-install_nginx_web_server ├── 2-setup_a_domain_name ├── 3-redirection ├── 4-not_found_page_404 ├── 7-puppet_install_nginx_web_server.pp ├── README.md ├── nginx, └── present, ├── 0x0D-web_stack_debugging_0 ├── 0-give_me_a_page └── README.md ├── 0x0E-web_stack_debugging_1 ├── 0-nginx_likes_port_80 ├── 1-debugging_made_short └── README.md ├── 0x0F-load_balancer ├── 0-custom_http_response_header ├── 1-install_load_balancer ├── 2-puppet_custom_http_response_header.pp └── README.md ├── 0x10-https_ssl ├── 0-world_wide_web ├── 1-haproxy_ssl_termination ├── 100-redirect_http_to_https └── README.md ├── 0x11-what_happens_when_your_type_google_com_in_your_browser_and_press_enter ├── 0-blog_post ├── 1-what_happen_when_diagram ├── 2-contribution-to_what-happens-when_github_answer └── README.md ├── 0x12-web_stack_debugging_2 ├── 0-iamsomeoneelse ├── 1-run_nginx_as_nginx ├── 100-fix_in_7_lines_or_less └── README.md ├── 0x13-firewall ├── 0-block_all_incoming_traffic_but └── README.md ├── 0x14-mysql ├── 4-mysql_configuration_primary ├── 4-mysql_configuration_replica ├── 5-mysql_backup └── README.md ├── 0x15-api ├── 0-gather_data_from_an_API.py ├── 1-export_to_CSV.py ├── 2-export_to_JSON.py ├── 3-dictionary_of_list_of_dictionaries.py └── README.md ├── 0x16-api_advanced ├── 0-subs.py ├── 1-top_ten.py ├── 100-count.py ├── 2-recurse.py └── README.md ├── 0x17-web_stack_debugging_3 ├── 0-strace_is_your_friend.pp └── README.md ├── 0x18-webstack_monitoring ├── 2-setup_datadog ├── README.md ├── Task_1.png └── Task_2.png ├── 0x19-postmortem ├── Blog_Post.md ├── README.md └── post-mortem-meetings.jpg ├── 0x1A-application_server ├── 2-app_server-nginx_config ├── 3-app_server-nginx_config ├── 4-app_server-nginx_config ├── 4-reload_gunicorn_no_downtime ├── 5-app_server-nginx_config ├── README.md └── gunicorn.service ├── 0x1B-web_stack_debugging_4 ├── 0-the_sky_is_the_limit_not.pp ├── 1-user_limit.pp └── README.md ├── README.md ├── attack_is_the_best_defense ├── 0-sniffing ├── 1-dictionary_attack └── README.md └── command_line_for_the_win ├── 0-first_9_tasks.png ├── 1-next_9_tasks.png ├── 2-next_9-tasks.png ├── README.md └── Solutions.md /0x00-shell_basics/0-current_working_directory: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | pwd 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/1-listit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/10-back: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd - 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/100-lets_move: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mv [[:upper:]]* /tmp/u 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/101-clean_emacs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm *~ 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/102-tree: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p welcome/to/school 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/103-commas: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -map 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/11-lists: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -al . .. /boot 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/12-file_type: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | file /tmp/iamafile 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/13-symbolic_link: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ln -s /bin/ls __ls__ 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/14-copy_html: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cp -rua *.html ../ 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/2-bring_me_home: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/3-listfiles: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -l 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/4-listmorefiles: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -la 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/5-listfilesdigitonly: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -lna 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/6-firstdirectory: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir /tmp/my_first_directory/ 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/7-movethatfile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mv /tmp/betty /tmp/my_first_directory/betty 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/8-firstdelete: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm /tmp/my_first_directory/betty 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/9-firstdirdeletion: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rmdir /tmp/my_first_directory 3 | -------------------------------------------------------------------------------- /0x00-shell_basics/README.md: -------------------------------------------------------------------------------- 1 | # Write a script that prints the absolute path name of the current working directory. 2 | # Display the contents list of your current directory. 3 | # Write a script that changes the working directory to the user’s home directory. 4 | # Display current directory contents in a long format 5 | # Display current directory contents, including hidden files (starting with .). Use the long format 6 | # Display current directory contents. 7 | - Long format 8 | - with user and group IDs displayed numerically 9 | - And hidden files (starting with .) 10 | # Create a script that creates a directory named my_first_directory in the /tmp/ directory. 11 | # Move the file betty from /tmp/ to /tmp/my_first_directory. 12 | # Delete the file betty. 13 | # Delete the directory my_first_directory that is in the /tmp directory. 14 | # Write a script that changes the working directory to the previous one. 15 | # Write a script that lists all files (even ones with names beginning with a period character, which are normally hidden) 16 | # in the current directory and the parent of the working directory and the /boot directory (in this order), in long format. 17 | # Write a script that prints the type of the file named iamafile. The file iamafile will be in the /tmp directory when we will run your script. 18 | # Create a symbolic link to /bin/ls, named __ls__. The symbolic link should be created in the current working directory. 19 | # Create a script that copies all the HTML files from the current working directory to the parent of the working directory, 20 | # but only copy files that did not exist in the parent of the working directory or were newer than the versions in the parent 21 | # of the working directory. You can consider that all HTML files have the extension .html 22 | # Create a script that moves all files beginning with an uppercase letter to the directory /tmp/u. 23 | # Create a script that deletes all files in the current working directory that end with the character ~. 24 | # Create a script that creates the directories welcome/, welcome/to/ and welcome/to/school in the current directory. 25 | # Write a command that lists all the files and directories of the current directory, separated by commas (,). 26 | # Directory names should end with a slash (/). 27 | # Files and directories starting with a dot (.) should be listed 28 | # The listing should be alpha ordered, except for the directories . and .. which should be listed at the very beginning 29 | # Only digits and letters are used to sort; Digits should come first 30 | # You can assume that all the files we will test with will have at least one letter or one digit 31 | # The listing should end with a new line# Write a script that prints the absolute path name of the current working directory. 32 | # Create a magic file school.mgc that can be used with the command file to detect School data files. School data files always contain the string SCHOOL at offset 0. 33 | 34 | 35 | -------------------------------------------------------------------------------- /0x00-shell_basics/__ls__: -------------------------------------------------------------------------------- 1 | /bin/ls -------------------------------------------------------------------------------- /0x00-shell_basics/school.mgc: -------------------------------------------------------------------------------- 1 | 0 string SCHOOL School data 2 | !:mime School 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/0-iam_betty: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | su betty 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/1-who_am_i: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | whoami 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/10-mirror_permissions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod --reference=olleh hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/100-change_owner_and_group: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chown vincent:staff * 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/101-symbolic_link_permissions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chown -h vincent:staff _hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/102-if_only: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chown --from=guillaume betty hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/103-Star_Wars: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | telnet towel.blinkenlights.nl 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/11-directories_permissions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo chmod -R +111 */ 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/12-directory_permissions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -m 751 my_dir 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/13-change_group: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chgrp school hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/2-groups: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | groups 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/3-new_owner: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chown betty hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/4-empty: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | touch hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/5-execute: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod u+x hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/6-multiple_permissions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod ug+x,o+r hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/7-everybody: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod ugo+x hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/8-James_Bond: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod 007 hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/9-John_Doe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod 753 hello 3 | -------------------------------------------------------------------------------- /0x01-shell_permissions/README.md: -------------------------------------------------------------------------------- 1 | 2 | Shel- permissions 3 | Shell, permissions 4 | What do the commands chmod, sudo, su, chown, chgrp do 5 | Linux file permissio How to represent each of the three sets of permissions (owner, group, and other) as a single digit 6 | How to change permissions, owner and group of a file 7 | Why cant a normal user chown a file 8 | How to run a command with root privileges 9 | How to change user ID or become superuser 10 | How to create a user 11 | How to create a group 12 | How to print real and effective user and group IDs 13 | How to print the groups a user is in 14 | How to print the effective userid 15 | -------------------------------------------------------------------------------- /0x02-shell_redirections/0-hello_world: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo Hello, World 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/1-confused_smiley: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo \"\(Ôo\)\' 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/10-no_more_js: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | find . -name "*.js" -type f -delete 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/100-empty_casks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | find . -empty -printf "%f\n" 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/101-gifs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | find . -type f -name "*.gif" -printf "%f\n"| rev | cut -d '.' -f2- | rev | LC_ALL=C sort -f 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/102-acrostic: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo -ne $(cut -c-1 | tr -d '\n')'\n' 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/103-the_biggest_fan: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | tail -n +2 | cut -f1 | sort | uniq -c | sort -nr -k 1,1 | cut -c 9- | head -11 3 | 4 | -------------------------------------------------------------------------------- /0x02-shell_redirections/11-directories: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | find . -mindepth 1 -type d | wc -l 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/12-newest_files: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -t | head 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/13-unique: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sort | uniq -u 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/14-findthatword: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep root /etc/passwd 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/15-countthatword: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep -c bin /etc/passwd 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/16-whatsnext: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat /etc/passwd | grep -A 3 "root" 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/17-hidethisword: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep -v bin /etc/passwd 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/18-letteronly: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep ^[[:alpha:]] /etc/ssh/sshd_config 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/19-AZ: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | tr 'Ac' 'Ze' 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/2-hellofile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat /etc/passwd 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/20-hiago: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | tr -d 'Cc' 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/208: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Sessions - new | Intranet 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
63 | 64 |
65 | 66 |
67 | 68 | 70 | 71 |
72 | 73 | 74 |
75 |
76 | 77 |
78 | 79 |
80 |
81 | 82 |
83 | 84 |
85 | 86 | 87 |
88 | 89 |
90 | 91 |
92 |
93 | 113 | 114 | 115 |
116 | 117 | 118 |
119 | 120 | 121 |
122 | 123 | 124 | 125 | 126 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /0x02-shell_redirections/21-reverse: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rev 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/22-users_and_homes: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cut -d":" --fields=1,6 /etc/passwd | sort 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/3-twofiles: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat /etc/passwd /etc/hosts 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/4-lastlines: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | tail /etc/passwd 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/5-firstlines: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | head /etc/passwd 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/6-third_line: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | head -n 3 iacta | tail -n 1 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/7-file: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Best School" | cat > '\*\\'\''"Best School"\'\''\\*$\?\*\*\*\*\*:)' 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/8-cwd_state: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ls -la > ls_cwd_content 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/9-duplicate_last_line: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | tail -n 1 iacta | cat >> iacta 3 | -------------------------------------------------------------------------------- /0x02-shell_redirections/README.md: -------------------------------------------------------------------------------- 1 | Shell, I/O Redirections and filters 2 | What do the commands head, tail, find, wc, sort, uniq, grep, tr do 3 | How to redirect standard output to a file 4 | How to get standard input from a file instead of the keyboard 5 | How to send the output from one program to the input of another program 6 | How to combine commands and filters with redirections 7 | 8 | Special Characters 9 | 10 | What are special characters 11 | Understand what do the white spaces, single quotes, double quotes, backslash, comment, pipe, command separator, tilde and how and when to use them 12 | 13 | Other Man Pages 14 | 15 | How to display a line of text 16 | How to concatenate files and print on the standard output 17 | How to reverse a string 18 | How to remove sections from each line of files 19 | What is the /etc/passwd file and what is its format 20 | What is the /etc/shadow file and what is its format 21 | 22 | Requirements 23 | General 24 | 25 | Allowed editors: vi, vim, emacs 26 | All your scripts will be tested on Ubuntu 14.04 LTS 27 | All your scripts should be exactly two lines long ($ wc -l file should print 2) 28 | All your files should end with a new line (why?) 29 | The first line of all your files should be exactly #!/bin/bash 30 | A README.md file, at the root of the folder of the project, describing what each script is doing 31 | You are not allowed to use backticks, &&, || or ; 32 | All your files must be executable 33 | You are not allowed to use sed or awk 34 | -------------------------------------------------------------------------------- /0x02-shell_redirections/\*\\'"Best School"\'\\*$\?\*\*\*\*\*:): -------------------------------------------------------------------------------- 1 | Best School 2 | -------------------------------------------------------------------------------- /0x02-shell_redirections/iacta: -------------------------------------------------------------------------------- 1 | Alea iacta est ("The die is cast") is a Latin phrase attributed by Suetonius 2 | (as iacta alea est) to Julius Caesar on January 10, 49 BC 3 | as he led his army across the Rubicon river in Northern Italy. With this step, 4 | he entered Italy at the head of his army in defiance of the Senate and began 5 | his long civil war against Pompey and the Optimates. The phrase has been 6 | adopted in Italian (Il dado è tratto), Romanian (Zarurile au fost aruncate), 7 | Spanish (La suerte está echada), French (Les dés sont jetés), Portuguese (A 8 | sorte está lançada), Dutch (De teerling is geworpen), 9 | German (Der Würfel ist gefallen), Hungarian (A kocka el van vetve) and many other languages to 10 | indicate that events have passed a point of no return. 11 | 12 | Read more: https://en.wikipedia.org/wiki/Alea_iacta_est 13 | julien@ubuntu:/tmp/h$ ./9-duplicate_last_line 14 | julien@ubuntu:/tmp/h$ cat iacta 15 | Alea iacta est 16 | 17 | Alea iacta est ("The die is cast") is a Latin phrase attributed by Suetonius 18 | (as iacta alea est) to Julius Caesar on January 10, 49 BC 19 | as he led his army across the Rubicon river in Northern Italy. With this step, 20 | he entered Italy at the head of his army in defiance of the Senate and began 21 | his long civil war against Pompey and the Optimates. The phrase has been 22 | adopted in Italian (Il dado è tratto), Romanian (Zarurile au fost aruncate), 23 | Spanish (La suerte está echada), French (Les dés sont jetés), Portuguese (A 24 | sorte está lançada), Dutch (De teerling is geworpen), 25 | German (Der Würfel ist gefallen), Hungarian (A kocka el van vetve) and many other languages to 26 | indicate that events have passed a point of no return. 27 | 28 | Read more: https://en.wikipedia.org/wiki/Alea_iacta_est 29 | Read more: https://en.wikipedia.org/wiki/Alea_iacta_est 30 | Read more: https://en.wikipedia.org/wiki/Alea_iacta_est 31 | -------------------------------------------------------------------------------- /0x02-shell_redirections/ls_cwd_content: -------------------------------------------------------------------------------- 1 | total 116 2 | drwxr-xr-x 2 root root 4096 Mar 8 00:38 . 3 | drwxr-xr-x 6 root root 121 Mar 7 23:26 .. 4 | -rwxr--r-- 1 root root 30 Mar 8 00:24 0-hello_world 5 | -rw-r--r-- 1 root root 104 Mar 8 00:21 101-gifs 6 | -rw-r--r-- 1 root root 50 Mar 8 00:21 102-acrostic 7 | -rw-r--r-- 1 root root 92 Mar 8 00:21 103-the_biggest_fan 8 | -rw-r--r-- 1 root root 48 Mar 8 00:21 10-no_more_js 9 | -rw-r--r-- 1 root root 47 Mar 8 00:21 11-directories 10 | -rw-r--r-- 1 root root 25 Mar 8 00:21 12-newest_files 11 | -rw-r--r-- 1 root root 27 Mar 8 00:21 13-unique 12 | -rw-r--r-- 1 root root 34 Mar 8 00:21 14-findthatword 13 | -rw-r--r-- 1 root root 36 Mar 8 00:21 15-countthatword 14 | -rw-r--r-- 1 root root 47 Mar 8 00:21 16-whatsnext 15 | -rw-r--r-- 1 root root 36 Mar 8 00:21 17-hidethisword 16 | -rw-r--r-- 1 root root 52 Mar 8 00:21 18-letteronly 17 | -rw-r--r-- 1 root root 25 Mar 8 00:21 19-AZ 18 | -rwxr--r-- 1 root root 29 Mar 8 00:28 1-confused_smiley 19 | -rw-r--r-- 1 root root 23 Mar 8 00:21 20-hiago 20 | -rw-r--r-- 1 root root 16 Mar 8 00:21 21-reverse 21 | -rw-r--r-- 1 root root 54 Mar 8 00:21 22-users_and_homes 22 | -rwxr--r-- 1 root root 28 Mar 8 00:21 2-hellofile 23 | -rwxr--r-- 1 root root 39 Mar 8 00:21 3-twofiles 24 | -rwxr--r-- 1 root root 29 Mar 8 00:21 4-lastlines 25 | -rwxr--r-- 1 root root 29 Mar 8 00:21 5-firstlines 26 | -rwxr--r-- 1 root root 40 Mar 8 00:21 6-third_line 27 | -rwxr--r-- 1 root root 86 Mar 8 00:21 7-file 28 | -rwxr--r-- 1 root root 36 Mar 8 00:21 8-cwd_state 29 | -rw-r--r-- 1 root root 43 Mar 8 00:21 9-duplicate_last_line 30 | -rw-r--r-- 1 root root 12 Mar 8 00:38 \*\\'"Best School"\'\\*$\?\*\*\*\*\*:) 31 | -rw-r--r-- 1 root root 0 Mar 8 00:38 ls_cwd_content 32 | -rw-r--r-- 1 root root 1416 Mar 8 00:21 README.md 33 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/.4-global_variables.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x03-shell_variables_expansions/.4-global_variables.swp -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/0-alias: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | alias ls="rm *" 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/1-hello_you: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo hello $USER 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/10-love_exponent_breath: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $(($BREATH**$LOVE)) 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/100-decimal_to_hexadecimal: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | printf "%x\n" $DECIMAL 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/101-rot13: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | tr 'A-Za-z' 'N-ZA-Mn-za-m' 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/102-odd: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | paste -d" " - - | cut -d " " -f 1 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/103-water_and_stir: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | printf '%o\n' $(( 5#$( echo $WATER | tr water 01234) + 5#$( echo $STIR | tr stir. 01234 ) )) | tr 01234567 bestchol 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/11-binary_to_decimal: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $((2#$BINARY)) 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/12-combinations: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo {a..z}{a..z} | tr ' ' '\n' | grep -v oo 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/13-print_float: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | printf "%0.2f\n" $NUM 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/2-path: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PATH=$PATH:/action 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/3-paths: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $PATH | tr ":" "\n" | wc -l 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/4-global_variables: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | printenv 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/5-local_variables: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/6-create_local_variable: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | BEST=School 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/7-create_global_variable: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export BEST=School 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/8-true_knowledge: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $(($TRUEKNOWLEDGE+128)) 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/9-divide_and_rule: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $(($POWER/$DIVIDE)) 3 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/README.md: -------------------------------------------------------------------------------- 1 | Shell Initialization Files 2 | 3 | What are the /etc/profile file and the /etc/profile.d directory 4 | What is the ~/.bashrc file 5 | Variables 6 | 7 | What is the difference between a local and a global variable 8 | What is a reserved variable 9 | How to create, update and delete shell variables 10 | What are the roles of the following reserved variables: HOME, PATH, PS1 11 | What are special parameters 12 | What is the special parameter $?? 13 | Expansions 14 | 15 | What is expansion and how to use them 16 | What is the difference between single and double quotes and how to use them properly 17 | How to do command substitution with $() and backticks 18 | Shell Arithmetic 19 | 20 | How to perform arithmetic operations with the shell 21 | 22 | The alias Command 23 | 24 | How to create an alias 25 | How to list aliases 26 | How to temporarily disable an alias 27 | 28 | Requirements 29 | General 30 | 31 | Allowed editors: vi, vim, emacs 32 | All your scripts will be tested on Ubuntu 20.04 LTS 33 | All your scripts should be exactly two lines long ($ wc -l file should print 2) 34 | All your files should end with a new line (why?) 35 | The first line of all your files should be exactly #!/bin/bash 36 | A README.md file, at the root of the folder of the project, describing what each script is doing 37 | You are not allowed to use &&, || or ; 38 | You are not allowed to use bc, sed or awk 39 | All your files must be executable 40 | 41 | -------------------------------------------------------------------------------- /0x03-shell_variables_expansions/quote: -------------------------------------------------------------------------------- 1 | "Everyone is a proponent of strong encryption." 2 | - Dorothy E. Denning 3 | -------------------------------------------------------------------------------- /0x04-loops_conditions_and_parsing/.101-tell_the_story_of_passwd.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x04-loops_conditions_and_parsing/.101-tell_the_story_of_passwd.swp -------------------------------------------------------------------------------- /0x04-loops_conditions_and_parsing/0-RSA_public_key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/lAoAVjSPhTUUkWd2KSQqMO0ur9o+nGGzjlVxb0BaBWa6p2sge75Ga/0lt2sBAJSw+tCtsMq6vqVqlWjLd91FVQlCVLaQ6kJN13Btu6w0Low21Wjyt/4IBRoZ9Zt+REwolbwLHp5oEqzup03sAaLbXTplztsSNv/fRf43flU+H6oqaDQx9nyzCxwhz2CTxTbMve59kCsts8DipqwOumgEBghWBsiSbo6LljbBpAazn57YDs7ijeox/kr5lOhnPKiFTH7GMvwCdXTYhTSBrwAhWhSgCt2Mb6d/bfuGHOqi35sNQUEj3pav61aDreifxwaKf65fWTnME6koD5VnhfNbImCYg9b5qamOKSP2Hvvcfimmqg14uD/tc42Xf5BMtenAXKKQ+UBd9yOdwGKxwTyEfbzTTX72VPkZEltazmaVoJLUjBJ84JyUObsmXwJei3fkjDlwxq+D9HJw9U5bzX8DDUWwxg8/xsE7kUq7qDdzkHtXz22bjfjAJWzVqkkQakE= root@1098f71136ac 2 | -------------------------------------------------------------------------------- /0x04-loops_conditions_and_parsing/1-for_best_school: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is displaying "Best School" 10 times 3 | 4 | for ((i = 1; i <= 10; i++)); do 5 | echo "Best School" 6 | done 7 | -------------------------------------------------------------------------------- /0x04-loops_conditions_and_parsing/10-fizzbuzz: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # displays numbers from 1 to 100 FizzBuzz, Fizz, Buzz 3 | 4 | for i in {1..100} 5 | do 6 | if ((i % 15 == 0 )) 7 | then 8 | echo "FizzBuzz" 9 | elif ((i % 3 == 0 )) 10 | then 11 | echo "Fizz" 12 | elif ((i % 5 == 0 )) 13 | then 14 | echo "Buzz" 15 | else echo "$i" 16 | fi 17 | done 18 | -------------------------------------------------------------------------------- /0x04-loops_conditions_and_parsing/100-read_and_cut: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # this script displays the content of the file /etc/passwd 3 | 4 | while x=":" read -r FILE 5 | do 6 | echo "$FILE" | cut -d":" -f1,3,6 7 | done /var/run/myscript.pid 5 | trap 'echo "I hate the kill command"; rm /var/run/myscript.pid; exit 0;' SIGTERM 6 | trap 'echo "Y U no love me?!"' SIGINT 7 | trap 'rm /var/run/myscript.pid; exit 0;' SIGQUIT 8 | while [ $true ]; do 9 | echo 'To infinity and beyond' 10 | sleep 2 11 | done; 12 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/101-manage_my_process: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Manages a daemon 3 | if [[ "$#" == "1" ]]; then 4 | if [[ "$1" == "start" ]]; then 5 | ./manage_my_process & 6 | echo "$!" > /var/run/my_process.pid 7 | echo "manage_my_process started" 8 | elif [[ "$1" == "stop" ]]; then 9 | if test -f "/var/run/my_process.pid"; then 10 | kill "$(cat /var/run/my_process.pid)" 11 | fi 12 | rm /var/run/my_process.pid 13 | echo "manage_my_process stopped" 14 | elif [[ "$1" == "restart" ]]; then 15 | # stop program 16 | if test -f "/var/run/my_process.pid"; then 17 | kill "$(cat /var/run/my_process.pid)" 18 | fi 19 | # start program 20 | ./manage_my_process & 21 | echo "$!" > /var/run/my_process.pid 22 | echo "manage_my_process restarted" 23 | else 24 | echo "Usage: manage_my_process {start|stop|restart}" 25 | fi 26 | else 27 | echo "Usage: manage_my_process {start|stop|restart}" 28 | fi 29 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/101-manage_my_process,: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # manager for manage_my_process 3 | case $1 in 4 | "start") 5 | ./manage_my_process & 6 | echo $! > /var/run/my_process.pid 7 | echo 'manage_my_process started' 8 | ;; 9 | "restart") 10 | id=$(cat /var/run/my_process.pid) 11 | kill -s SIGSTOP $id 12 | rm /var/run/my_process.pid 13 | ./manage_my_process & 14 | echo $! > /var/run/my_process.pid 15 | echo 'manage_my_process restarted' 16 | ;; 17 | "stop") 18 | id=$(cat /var/run/my_process.pid) 19 | kill -s SIGSTOP $id 20 | rm /var/run/my_process.pid 21 | echo 'manage_my_process stopped' 22 | ;; 23 | *) 24 | echo 'Usage: manage_my_process {start|stop|restart}' 25 | ;; 26 | esac 27 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/102-zombie.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | /** 5 | * infinite_while - given fuction for the created zombie 6 | * Return: 0 if success 7 | */ 8 | int infinite_while(void) 9 | { 10 | while (1) 11 | { 12 | sleep(1); 13 | } 14 | return (0); 15 | } 16 | /** 17 | * main - function that created 5 zombies processes 18 | * Return: 0 if success 19 | */ 20 | int main(void) 21 | { 22 | int process; 23 | pid_t zombie_pid; 24 | 25 | process = 0; 26 | while (process < 5) 27 | { 28 | zombie_pid = fork(); 29 | if (zombie_pid > 0) 30 | { 31 | printf("Zombie process created, PID: %d\n", zombie_pid); 32 | } 33 | else 34 | exit(0); 35 | process++; 36 | } 37 | infinite_while(); 38 | return (0); 39 | } 40 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/2-show_your_bash_pid: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # script that displays lines containing the bash word, getting PID of bash proc 3 | # shellcheck disable=SC2009 4 | ps -faux | grep bash 5 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/3-show_your_bash_pid_made_easy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # cript that displays the PID, along with the process name 3 | pgrep -l bash 4 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/4-to_infinity_and_beyond: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Bash script that displays To infinity and beyond indefinitely 3 | while true 4 | do 5 | echo "To infinity and beyond" 6 | sleep 2 7 | done 8 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/5-dont_stop_me_now: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Bash script that kills 4-to_infinity_and_beyond 3 | kill "$(pgrep -f "4-to_infinity_and_beyond")" 4 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/6-stop_me_if_you_can: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # script that stops 4-to_infinity_and_beyond process 3 | pkill -f 4-to_infinity_and_beyond 4 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/7-highlander: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # script that displays To inifity... and I am invisible !!! 3 | trap "echo I am invincible!!!" SIGTERM 4 | i=1 5 | while [ $i -lt 2 ] 6 | do 7 | echo "To infinity and beyond" 8 | sleep 2 9 | done 10 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/8-beheaded_process: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # script that kills the process 7-highlander 3 | pkill -SIGKILL -f 7-highlander 4 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/README.md: -------------------------------------------------------------------------------- 1 | # 05. Processes and signals 2 | 3 | General 4 | 5 | What is a PID 6 | What is a process 7 | How to find a process’ PID 8 | How to kill a process 9 | What is a signal 10 | What are the 2 signals that cannot be ignored 11 | 12 | -------------------------------------------------------------------------------- /0x05-processes_and_signals/manage_my_process: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Writes a string to a file indefinitely 3 | while [[ 1 -eq 1 ]]; do 4 | echo "I am alive!" >> /tmp/my_process 5 | sleep 2 6 | done 7 | -------------------------------------------------------------------------------- /0x06-regular_expressions/0-simply_match_school.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/School/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/1-repetition_token_0.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/hbt{2,5}n/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/100-textme.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/\[from:(\+?\w*)\]\s\[to:(\+?\w*)\]\s\[flags:(\S*)\]/).join(',') 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/2-repetition_token_1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/hb?tn/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/3-repetition_token_2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/hbt+n/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/4-repetition_token_3.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/hbt*n/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/5-beginning_and_end.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/^h.n$/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/6-phone_number.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/^\d{10}$/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/7-OMG_WHY_ARE_YOU_SHOUTING.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts ARGV[0].scan(/[A-Z]/).join 3 | -------------------------------------------------------------------------------- /0x06-regular_expressions/README.md: -------------------------------------------------------------------------------- 1 | # Regular expression 2 | -------------------------------------------------------------------------------- /0x07-networking_basics/0-OSI_model: -------------------------------------------------------------------------------- 1 | 2 2 | 2 3 | -------------------------------------------------------------------------------- /0x07-networking_basics/1-types_of_network: -------------------------------------------------------------------------------- 1 | 3 2 | 2 3 | 1 4 | -------------------------------------------------------------------------------- /0x07-networking_basics/2-MAC_and_IP_address: -------------------------------------------------------------------------------- 1 | 2 2 | 1 3 | -------------------------------------------------------------------------------- /0x07-networking_basics/3-UDP_and_TCP: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 1 4 | -------------------------------------------------------------------------------- /0x07-networking_basics/4-TCP_and_UDP_ports: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is displaying listening ports. 3 | 4 | netstat -lp 5 | -------------------------------------------------------------------------------- /0x07-networking_basics/5-is_the_host_on_the_network: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is pinging 5 times the given as parameter ip adress. 3 | 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: 5-is_the_host_on_the_network {IP_ADDRESS}" 6 | else 7 | ping -c5 "$1" 8 | fi 9 | -------------------------------------------------------------------------------- /0x07-networking_basics/README.md: -------------------------------------------------------------------------------- 1 | # 0x07. Networking basics #0 2 | ### Tasks 3 | 0. OSI model 4 | 1. Types of network 5 | 2. MAC and IP address 6 | 3. UDP and TCP 7 | 4. TCP and UDP ports 8 | 5. Is the host on the network 9 | 10 | -------------------------------------------------------------------------------- /0x08-networking_basics_2/0-change_your_home_IP: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is modifying hosts. 3 | 4 | cp /etc/hosts ~/hosts.new 5 | sed -i 's/127.*$/127.0.0.2 localhost\n8.8.8.8 facebook.com/' ~/hosts.new 6 | cp -f ~/hosts.new /etc/hosts 7 | -------------------------------------------------------------------------------- /0x08-networking_basics_2/1-show_attached_IPs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Displays all acive IPv4 addresses on the machine. 3 | 4 | ifconfig | grep -Eo "inet (addr:)?([0-9]*\.){3}[0-9]*" | cut -b 11- 5 | -------------------------------------------------------------------------------- /0x08-networking_basics_2/100-port_listening_on_localhost: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script is listening on port 98 on localhost. 3 | 4 | nc -l 98 5 | -------------------------------------------------------------------------------- /0x08-networking_basics_2/README.md: -------------------------------------------------------------------------------- 1 | # 0x08-networking_basics_2 2 | ### Tasks 3 | 0. Change your home IP 4 | 1. Show attached IPs 5 | 6 | -------------------------------------------------------------------------------- /0x09-web_infrastructure_design/0-simple_web_stack: -------------------------------------------------------------------------------- 1 | https://imgur.com/yhvR3sT 2 | -------------------------------------------------------------------------------- /0x09-web_infrastructure_design/1-distributed_web_infrastructure: -------------------------------------------------------------------------------- 1 | https://imgur.com/d9WX8E3 2 | -------------------------------------------------------------------------------- /0x09-web_infrastructure_design/2-secured_and_monitored_web_infrastructure: -------------------------------------------------------------------------------- 1 | https://imgur.com/3z7MIKd 2 | -------------------------------------------------------------------------------- /0x09-web_infrastructure_design/3-scale_up: -------------------------------------------------------------------------------- 1 | https://imgur.com/ksiNWFY 2 | -------------------------------------------------------------------------------- /0x09-web_infrastructure_design/README.md: -------------------------------------------------------------------------------- 1 | # Web infrastructure design 2 | 3 | 4 | 5 | ### Tasks 6 | 0. Simple web stack 7 | 1. Distributed web infrastructure 8 | 2. Secured and monitored web infrastructure 9 | 3. Scale up 10 | 11 | 12 | ## Authors 13 | 14 | - Tewodros Atirsaw Awedew 15 | -------------------------------------------------------------------------------- /0x0A-configuration_management/0-create_a_file.pp: -------------------------------------------------------------------------------- 1 | # Creates a file in /tmp. 2 | 3 | file { 'school': 4 | name => '/tmp/school', 5 | mode => '0744', 6 | owner => 'www-data', 7 | group => 'www-data', 8 | content => 'I love Puppet', 9 | } 10 | -------------------------------------------------------------------------------- /0x0A-configuration_management/1-install_a_package.pp: -------------------------------------------------------------------------------- 1 | # Installs a package 2 | package { 'flask': 3 | ensure => '2.1.0', 4 | provider => 'pip' 5 | } 6 | -------------------------------------------------------------------------------- /0x0A-configuration_management/2-execute_a_command.pp: -------------------------------------------------------------------------------- 1 | # Kills the killmenow process. 2 | 3 | exec { 'killmenow': 4 | command => 'pkill killmenow', 5 | path => '/usr/local/bin/:/usr/bin:/bin/', 6 | } 7 | -------------------------------------------------------------------------------- /0x0A-configuration_management/README.md: -------------------------------------------------------------------------------- 1 | # Configuration management 2 | ### Tasks 3 | 0. Create a file 4 | 1. Install a package 5 | 2. Execute a command 6 | ##Background Context 7 | 8 | 9 | When I was working for SlideShare, I worked on an auto-remediation tool called Skynet that monitored, scaled and fixed Cloud infrastructure. I was using a parallel job-execution system called MCollective that allowed me to execute commands to one or multiple servers at the same time. I could apply an action to a selected set of servers by applying a filter such as the server’s hostname or any other metadata we had (server type, server environment…). At some point, a bug was present in my code that sent nil to the filter method. 10 | 11 | There were 2 pieces of bad news: 12 | 13 | When MCollective receives nil as an argument for its filter method, it takes this to mean ‘all servers’ 14 | The action I sent was to terminate the selected servers 15 | I started the parallel job-execution and after some time, I realized that it was taking longer than expected. Looking at logs I realized that I was shutting down SlideShare’s entire document conversion environment. Actually, 75% of all our conversion infrastructure servers had been shut down, resulting in users not able to convert their PDFs, powerpoints, and videos… Pretty bad! 16 | 17 | Thanks to Puppet, we were able to restore our infrastructure to normal operation in under 1H, pretty impressive. Imagine if we had to do everything manually: launching the servers, configuring and linking them, importing application code, starting every process, and obviously, fixing all the bugs (you should know by now that complicated infrastructure always goes sideways)… 18 | 19 | Obviously writing Puppet code for your infrastructure requires an investment of time and energy, but in the long term, it is for sure a must-have. 20 | ###Resources 21 | Read or watch: 22 | 23 | Intro to Configuration Management 24 | Puppet resource type: file (check “Resource types” for all manifest types in the left menu) 25 | Puppet’s Declarative Language: Modeling Instead of Scripting 26 | Puppet lint 27 | Puppet emacs mode 28 | Requirements 29 | General 30 | All your files will be interpreted on Ubuntu 20.04 LTS 31 | All your files should end with a new line 32 | A README.md file at the root of the folder of the project is mandatory 33 | Your Puppet manifests must pass puppet-lint version 2.1.1 without any errors 34 | Your Puppet manifests must run without error 35 | Your Puppet manifests first line must be a comment explaining what the Puppet manifest is about 36 | Your Puppet manifests files must end with the extension .pp 37 | 38 | -------------------------------------------------------------------------------- /0x0B-ssh/0-use_a_private_key: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script uses ssh to connect to a server using a private key 3 | 4 | ssh ubuntu@35.153.18.80 -i ~/.ssh/school 5 | -------------------------------------------------------------------------------- /0x0B-ssh/1-create_ssh_key_pair: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script creates an RSA key pair 3 | 4 | ssh-keygen -f school -b 4096 -P betty 5 | -------------------------------------------------------------------------------- /0x0B-ssh/100-puppet_ssh_config.pp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # connect to a server Execute a command 3 | 4 | exec { 'echo "PasswordAuthentication no\nIdentityFile ~/.ssh/school" >> /etc/ssh/ssh_config': 5 | path => '/bin/' 6 | } 7 | -------------------------------------------------------------------------------- /0x0B-ssh/2-ssh_config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Client configuration file 3 | # file with user config 4 | Host 54.224.46.152 5 | IdentityFile ~/.ssh/school 6 | PasswordAuthentication no 7 | -------------------------------------------------------------------------------- /0x0B-ssh/README.md: -------------------------------------------------------------------------------- 1 | # SSH 2 | 3 | 4 | 5 | ### Tasks 6 | 0. Use a private key 7 | 1. Create an SSH key pair 8 | 2. Client configuration file 9 | 3. Let me in! 10 | 11 | -------------------------------------------------------------------------------- /0x0C-web_server/.0-transfer_file.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x0C-web_server/.0-transfer_file.swp -------------------------------------------------------------------------------- /0x0C-web_server/.2-setup_a_domain_name.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x0C-web_server/.2-setup_a_domain_name.swo -------------------------------------------------------------------------------- /0x0C-web_server/.README.md.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x0C-web_server/.README.md.swp -------------------------------------------------------------------------------- /0x0C-web_server/0-transfer_file: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Transfers a file from Holberton's client to another. 3 | # Accepts four arguments: 4 | #+ The path to the file to be transferred. 5 | #+ The IP of the server to transfer the file to. 6 | #+ The username that scp connects with. 7 | #+ The path to the SSH private key that scp uses. 8 | 9 | if [ $# -lt 4 ] 10 | then 11 | echo "Usage: 0-transfer_file PATH_TO_FILE IP USERNAME PATH_TO_SSH_KEY" 12 | else 13 | scp -o StrictHostKeyChecking=no -i "$4" "$1" "$3@$2":~ 14 | fi 15 | -------------------------------------------------------------------------------- /0x0C-web_server/1-install_nginx_web_server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Installs, configures, and starts the server 3 | sudo apt-get update 4 | sudo apt-get -y install nginx 5 | sudo ufw allow 'Nginx HTTP' 6 | mkdir -p /var/www/html 7 | chmod -R 755 /var/www 8 | echo 'Hello World!' > /var/www/html/index.html 9 | SERVER_CONFIG=\ 10 | "server { 11 | listen 80 default_server; 12 | listen [::]:80 default_server; 13 | 14 | root /var/www/html; 15 | index index.html index.htm index.nginx-debian.html; 16 | 17 | server_name _; 18 | 19 | location / { 20 | try_files \$uri \$uri/ =404; 21 | } 22 | }" 23 | 24 | bash -c "echo -e '$SERVER_CONFIG' > /etc/nginx/sites-enabled/default" 25 | 26 | if [ "$(pgrep -c nginx)" -le 0 ]; then 27 | sudo service nginx start 28 | else 29 | sudo service nginx restart 30 | fi 31 | -------------------------------------------------------------------------------- /0x0C-web_server/2-setup_a_domain_name: -------------------------------------------------------------------------------- 1 | teddysolutions.tech 2 | -------------------------------------------------------------------------------- /0x0C-web_server/3-redirection: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Installs, configures, and starts the server 3 | sudo apt-get update 4 | sudo apt-get -y install nginx 5 | sudo ufw allow 'Nginx HTTP' 6 | mkdir -p /var/www/html/ 7 | sudo chmod -R 755 /var/www 8 | echo 'Hello World!' > /var/www/html/index.html 9 | SERVER_CONFIG=\ 10 | "server { 11 | listen 80 default_server; 12 | listen [::]:80 default_server; 13 | 14 | root /var/www/html; 15 | index index.html index.htm index.nginx-debian.html; 16 | 17 | server_name _; 18 | 19 | location / { 20 | try_files \$uri \$uri/ =404; 21 | } 22 | 23 | if (\$request_filename ~ redirect_me){ 24 | rewrite ^ https://sketchfab.com/bluepeno/models permanent; 25 | } 26 | }" 27 | 28 | bash -c "echo -e '$SERVER_CONFIG' > /etc/nginx/sites-enabled/default" 29 | 30 | if [ "$(pgrep -c nginx)" -le 0 ]; then 31 | sudo service nginx start 32 | else 33 | sudo service nginx restart 34 | fi 35 | -------------------------------------------------------------------------------- /0x0C-web_server/4-not_found_page_404: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Install Nginx, redirect and 404 3 | 4 | sudo apt update -y 5 | sudo apt upgrade -y 6 | sudo apt install nginx -y 7 | sudo service nginx start 8 | echo "Ceci n'est pas une page" | sudo tee /var/www/html/index.nginx-debian.html 9 | new_string='server_name _;\n\n\trewrite \^\/redirect_me https:\/\/www.youtube.com\/watch\?v=QH2-TGUlwu4 permanent;/' 10 | sudo sed -i "s/server_name _;\$/${new_string}" /etc/nginx/sites-available/default 11 | sudo sed -i "s/^\t\}$/\t\}\n\n\terror_page 404 \/404.html;/" /etc/nginx/sites-available/default 12 | sudo ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default 13 | echo "Ceci n'est pas une page" | sudo tee /var/www/html/404.html 14 | sudo service nginx restart 15 | -------------------------------------------------------------------------------- /0x0C-web_server/7-puppet_install_nginx_web_server.pp: -------------------------------------------------------------------------------- 1 | # This manifest installs ngix and adds redirect page 2 | 3 | package {'nginx': 4 | ensure => present, 5 | name => 'nginx', 6 | } 7 | 8 | file {'/var/www/html/index.html': 9 | ensure => present, 10 | path => '/var/www/html/index.html', 11 | content => 'Hello World!', 12 | } 13 | 14 | file_line { 'redirect_me': 15 | ensure => present, 16 | path => '/etc/nginx/sites-available/default', 17 | after => 'listen 80 default_server;', 18 | line => 'rewrite ^/redirect_me https://www.youtube.com/watch?v=QH2-TGUlwu4 permanent;', 19 | } 20 | 21 | service { 'nginx': 22 | ensure => running, 23 | hasrestart => true, 24 | require => Package['nginx'], 25 | subscribe => File_line['redirect_me'], 26 | } 27 | -------------------------------------------------------------------------------- /0x0C-web_server/README.md: -------------------------------------------------------------------------------- 1 | # Web server 2 | 3 | 4 | ### Tasks 5 | 0. Transfer a file to your server 6 | 2. Setup a domain name 7 | 3. Redirection 8 | 4. Not found page 404 9 | 5. Install Nginx web server (w/ Puppet) 10 | -------------------------------------------------------------------------------- /0x0C-web_server/nginx,: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x0C-web_server/nginx, -------------------------------------------------------------------------------- /0x0C-web_server/present,: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x0C-web_server/present, -------------------------------------------------------------------------------- /0x0D-web_stack_debugging_0/0-give_me_a_page: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #Script was use to fix a not function a we server 3 | sudo service apache2 restart 4 | -------------------------------------------------------------------------------- /0x0D-web_stack_debugging_0/README.md: -------------------------------------------------------------------------------- 1 | # Web stack debugging #0 2 | 3 | 4 | 5 | ### Tasks 6 | 0. Give me a page! 7 | -------------------------------------------------------------------------------- /0x0E-web_stack_debugging_1/0-nginx_likes_port_80: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Configures an Nginx server to listen on port 80. 3 | 4 | rm /etc/nginx/sites-enabled/default 5 | ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default 6 | service nginx restart 7 | -------------------------------------------------------------------------------- /0x0E-web_stack_debugging_1/1-debugging_made_short: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Configures an Nginx server to listen on port 80. 3 | ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default 4 | service nginx start 5 | kill "$(pgrep 'nginx' | head -1)" 6 | -------------------------------------------------------------------------------- /0x0E-web_stack_debugging_1/README.md: -------------------------------------------------------------------------------- 1 | # Web stack debugging #1 2 | 3 | 4 | ### Tasks 5 | 0. Nginx likes port 80 6 | 1. Make it sweet and short 7 | -------------------------------------------------------------------------------- /0x0F-load_balancer/0-custom_http_response_header: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Installs Nginx with the following configurations: 3 | #+ Listens on port 80. 4 | #+ Returns a page containing "Hello World!" when queried 5 | #+ at the root with a curl GET request. 6 | # Configures /redirect_me as a "301 Moved Permanently". 7 | # Includes a custom 404 page containing "Ceci n'est pas une page". 8 | 9 | sudo apt-get update 10 | sudo apt-get install -y nginx 11 | 12 | sudo mkdir /etc/nginx/html 13 | sudo touch /etc/nginx/html/index.html 14 | echo "Hello World!" > /etc/nginx/html/index.html 15 | sudo touch /etc/nginx/html/404.html 16 | echo "Ceci n'est pas une page" > /etc/nginx/html/404.html 17 | 18 | printf %s "server { 19 | listen 80; 20 | listen [::]:80 default_server; 21 | add_header X-Served-By $HOSTNAME; 22 | root /etc/nginx/html; 23 | index index.html index.htm; 24 | location /redirect_me { 25 | return 301 https://www.youtube.com/watch?v=QH2-TGUlwu4; 26 | } 27 | error_page 404 /404.html; 28 | location /404 { 29 | root /etc/nginx/html; 30 | internal; 31 | } 32 | }" > /etc/nginx/sites-available/default 33 | 34 | sudo service nginx restart 35 | -------------------------------------------------------------------------------- /0x0F-load_balancer/1-install_load_balancer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Installs HAProxy version 1.8 with the following configurations: 3 | #+ Enables management via the init script. 4 | #+ Distributes requests using a round-robin algorithm. 5 | 6 | sudo apt-get -y update 7 | sudo apt-get -y upgrade 8 | sudo apt-get -y install haproxy 9 | 10 | echo "ENABLED=1" >> /etc/default/haproxy 11 | sudo mv /etc/haproxy/haproxy.cfg{,.original} 12 | sudo touch /etc/haproxy/haproxy.cfg 13 | 14 | printf %s "global 15 | log 127.0.0.1 local0 notice 16 | maxconn 2000 17 | user haproxy 18 | group haproxy 19 | defaults 20 | log global 21 | mode http 22 | option httplog 23 | option dontlognull 24 | retries 3 25 | option redispatch 26 | timeout connect 5000 27 | timeout client 10000 28 | timeout server 10000 29 | listen hbnb 30 | bind 0.0.0.0:80 31 | mode http 32 | stats enable 33 | stats uri /haproxy?stats 34 | balance roundrobin 35 | option httpclose 36 | option forwardfor 37 | server 3593-web-01 18.204.5.22 check port 80 38 | server 3593-web-02 100.25.215.65 check port 80 39 | " >> /etc/haproxy/haproxy.cfg 40 | 41 | sudo service haproxy start 42 | -------------------------------------------------------------------------------- /0x0F-load_balancer/2-puppet_custom_http_response_header.pp: -------------------------------------------------------------------------------- 1 | # Script that setup a nginx web server on our server + redirection + header 2 | exec { 'update': 3 | command => '/usr/bin/apt-get update', 4 | } 5 | 6 | package { 'nginx': 7 | ensure => installed, 8 | name => 'nginx', 9 | require => Exec['update'], 10 | } 11 | 12 | file { '/var/www/html/index.html': 13 | ensure => 'present', 14 | path => '/var/www/html/index.html', 15 | content => 'Holberton School', 16 | require => Package['nginx'], 17 | } 18 | 19 | file_line { 'redirect_me': 20 | ensure => 'present', 21 | path => '/etc/nginx/sites-available/default', 22 | after => 'listen 80 default_server;', 23 | line => 'rewrite ^/redirect_me https://www.youtube.com/watch?v=QH2-TGUlwu4 permanent;', 24 | require => Package['nginx'], 25 | } 26 | 27 | file_line { 'addHeader': 28 | ensure => 'present', 29 | path => '/etc/nginx/sites-available/default', 30 | after => 'listen 80 default_server;', 31 | line => 'add_header X-Served-By $hostname;', 32 | require => Package['nginx'], 33 | } 34 | 35 | service { 'nginx': 36 | ensure => running, 37 | require => Package['nginx'], 38 | } 39 | -------------------------------------------------------------------------------- /0x0F-load_balancer/README.md: -------------------------------------------------------------------------------- 1 | # Load balancer 2 | 3 | ### Tasks 4 | 0. Double the number of webservers 5 | 1. Install your load balancer 6 | 2. Add a custom HTTP header with Puppet 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /0x10-https_ssl/0-world_wide_web: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: ./0-world_wide_web 3 | # Display information about subdomains. 4 | 5 | domain_information () { 6 | line=$(dig "$2"."$1" | grep -A1 'ANSWER SECTION:' | tr '\t' '\n' | tail -2 | tr '\n' ' ') 7 | echo "$2 $line" | awk '{print "The subdomain " $1 " is a " $2 " record and points to " $3}' 8 | } 9 | 10 | if [ "$#" == 1 ] 11 | then 12 | domain_information "$1" "www" 13 | domain_information "$1" "lb-01" 14 | domain_information "$1" "web-01" 15 | domain_information "$1" "web-02" 16 | elif [ "$#" == 2 ] 17 | then 18 | domain_information "$1" "$2" 19 | fi 20 | -------------------------------------------------------------------------------- /0x10-https_ssl/1-haproxy_ssl_termination: -------------------------------------------------------------------------------- 1 | global 2 | log /dev/log local0 3 | maxconn 2048 4 | user haproxy 5 | group haproxy 6 | tune.ssl.default-dh-param 2048 7 | 8 | defaults 9 | log global 10 | mode http 11 | option httplog 12 | option dontlognull 13 | retries 3 14 | option redispatch 15 | timeout connect 5000 16 | timeout client 10000 17 | timeout server 10000 18 | option forwardfor 19 | option http-server-close= 20 | 21 | frontend www-http 22 | bind 0.0.0.0:80 23 | reqadd X-Forwarded-Proto:\ http 24 | default_backend www-backend 25 | 26 | frontend www-https 27 | bind 0.0.0.0:443 ssl crt /etc/letsencrypt/live/www.teddy.tech/all.pem 28 | reqadd X-Forwarded-Proto:\ https 29 | acl letsencrypt-acl path_beg /.well-known/acme-challenge/ 30 | use_backend letsencrypt-backend if letsencrypt-acl 31 | default_backend www-backend 32 | 33 | backend www-backend 34 | balance roundrobin 35 | redirect scheme https if !{ ssl_fc } 36 | server 3593-web-01 44.210.83.85:80 check 37 | server 3593-web-02 3.236.84.6:80 check 38 | 39 | backend letsencrypt-backend 40 | server letsencrypt 127.0.0.1:54321 41 | -------------------------------------------------------------------------------- /0x10-https_ssl/100-redirect_http_to_https: -------------------------------------------------------------------------------- 1 | global 2 | log /dev/log local0 3 | maxconn 2048 4 | user haproxy 5 | group haproxy 6 | tune.ssl.default-dh-param 2048 7 | 8 | defaults 9 | log global 10 | mode http 11 | option httplog 12 | option dontlognull 13 | retries 3 14 | option redispatch 15 | timeout connect 5000 16 | timeout client 10000 17 | timeout server 10000 18 | option forwardfor 19 | option http-server-close 20 | 21 | frontend www-http 22 | bind 0.0.0.0:80 23 | reqadd X-Forwarded-Proto:\ http 24 | default_backend www-backend 25 | redirect scheme https code 301 if !{ ssl_fc } 26 | 27 | 28 | frontend www-https 29 | bind 0.0.0.0:443 ssl crt /etc/letsencrypt/live/www.topsentaa.tech/all.pem 30 | reqadd X-Forwarded-Proto:\ https 31 | acl letsencrypt-acl path_beg /.well-known/acme-challenge/ 32 | use_backend letsencrypt-backend if letsencrypt-acl 33 | default_backend www-backend 34 | 35 | backend www-backend 36 | balance roundrobin 37 | redirect scheme https if !{ ssl_fc } 38 | server 1329-web-01 34.73.127.101:80 check 39 | server 1329-web-02 18.205.59.182:80 check 40 | 41 | backend letsencrypt-backend 42 | server letsencrypt 127.0.0.1:54321 43 | -------------------------------------------------------------------------------- /0x10-https_ssl/README.md: -------------------------------------------------------------------------------- 1 | # HTTPS SSL 2 | 3 | 4 | ## Tasks 5 | 0. World wide web 6 | 1. HAproxy SSL termination 7 | 2. No loophole in your website traffic 8 | -------------------------------------------------------------------------------- /0x11-what_happens_when_your_type_google_com_in_your_browser_and_press_enter/0-blog_post: -------------------------------------------------------------------------------- 1 | https://www.linkedin.com/pulse/what-happens-when-you-type-httpswwwgooglecom-your-browser-awedew 2 | -------------------------------------------------------------------------------- /0x11-what_happens_when_your_type_google_com_in_your_browser_and_press_enter/1-what_happen_when_diagram: -------------------------------------------------------------------------------- 1 | https://imgur.com/a/MRrbd6j 2 | -------------------------------------------------------------------------------- /0x11-what_happens_when_your_type_google_com_in_your_browser_and_press_enter/2-contribution-to_what-happens-when_github_answer: -------------------------------------------------------------------------------- 1 | https://github.com/teddy004/what-happens-when 2 | -------------------------------------------------------------------------------- /0x11-what_happens_when_your_type_google_com_in_your_browser_and_press_enter/README.md: -------------------------------------------------------------------------------- 1 | # What happens when you type google.com in your browser and press Enter 2 | Requirements, your post must cover: 3 | 4 | _ DNS request 5 | _TCP/IP 6 | _Firewall 7 | _HTTPS/SSL 8 | _Load-balancer 9 | -Web server 10 | _ Application server 11 | _ Database 12 | 13 | -------------------------------------------------------------------------------- /0x12-web_stack_debugging_2/0-iamsomeoneelse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # run the whoami command under the user passed as an argument 3 | sudo -u "$1" whoami 4 | -------------------------------------------------------------------------------- /0x12-web_stack_debugging_2/1-run_nginx_as_nginx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # runs nginx as nginx 3 | pkill apache2 4 | chown nginx:nginx /etc/nginx/nginx.conf 5 | chmod 777 /etc/nginx/nginx.conf 6 | sed -i 's/80/8080/g' /etc/nginx/sites-available/default 7 | sudo -u nginx service nginx start 8 | -------------------------------------------------------------------------------- /0x12-web_stack_debugging_2/100-fix_in_7_lines_or_less: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # runs nginx as nginx 3 | pkill apache2 4 | chown nginx:nginx /etc/nginx/nginx.conf 5 | chmod 777 /etc/nginx/nginx.conf 6 | sed -i 's/80/8080/g' /etc/nginx/sites-available/default 7 | sudo -u nginx service nginx start 8 | -------------------------------------------------------------------------------- /0x12-web_stack_debugging_2/README.md: -------------------------------------------------------------------------------- 1 | # Web stack debugging #2 2 | 3 | 4 | 5 | 6 | ### Tasks 7 | 0. Run software as another user 8 | 1. Run Nginx as Nginx 9 | 2. 7 lines or less 10 | 11 | -------------------------------------------------------------------------------- /0x13-firewall/0-block_all_incoming_traffic_but: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # activating ufw and setting a couple of rules 3 | sudo ufw default deny incoming 4 | sudo ufw allow 22/tcp 5 | sudo ufw allow 443/tcp 6 | sudo ufw allow 80/tcp 7 | sudo ufw enable 8 | -------------------------------------------------------------------------------- /0x13-firewall/README.md: -------------------------------------------------------------------------------- 1 | # Firewall 2 | 3 | 4 | # Tasks 5 | 0. Block all incoming traffic but 6 | 1. Port forwarding 7 | -------------------------------------------------------------------------------- /0x14-mysql/4-mysql_configuration_primary: -------------------------------------------------------------------------------- 1 | # 2 | # The MySQL database server configuration file. 3 | # 4 | # You can copy this to one of: 5 | # - "/etc/mysql/my.cnf" to set global options, 6 | # - "~/.my.cnf" to set user-specific options. 7 | # 8 | # One can use all long options that the program supports. 9 | # Run program with --help to get a list of available options and with 10 | # --print-defaults to see which it would actually understand and use. 11 | # 12 | # For explanations see 13 | # http://dev.mysql.com/doc/mysql/en/server-system-variables.html 14 | 15 | # This will be passed to all mysql clients 16 | # It has been reported that passwords should be enclosed with ticks/quotes 17 | # escpecially if they contain "#" chars... 18 | # Remember to edit /etc/mysql/debian.cnf when changing the socket location. 19 | 20 | # Here is entries for some specific programs 21 | # The following values assume you have at least 32M ram 22 | 23 | [mysqld_safe] 24 | socket = /var/run/mysqld/mysqld.sock 25 | nice = 0 26 | 27 | [mysqld] 28 | # 29 | # * Basic Settings 30 | # 31 | user = mysql 32 | pid-file = /var/run/mysqld/mysqld.pid 33 | socket = /var/run/mysqld/mysqld.sock 34 | port = 3306 35 | basedir = /usr 36 | datadir = /var/lib/mysql 37 | tmpdir = /tmp 38 | lc-messages-dir = /usr/share/mysql 39 | skip-external-locking 40 | # 41 | # Instead of skip-networking the default is now to listen only on 42 | # localhost which is more compatible and is not less secure. 43 | # bind-address = 127.0.0.1 44 | # 45 | # * Fine Tuning 46 | # 47 | key_buffer_size = 16M 48 | max_allowed_packet = 16M 49 | thread_stack = 192K 50 | thread_cache_size = 8 51 | # This replaces the startup script and checks MyISAM tables if needed 52 | # the first time they are touched 53 | myisam-recover-options = BACKUP 54 | #max_connections = 100 55 | #table_cache = 64 56 | #thread_concurrency = 10 57 | # 58 | # * Query Cache Configuration 59 | # 60 | query_cache_limit = 1M 61 | query_cache_size = 16M 62 | # 63 | # * Logging and Replication 64 | # 65 | # Both location gets rotated by the cronjob. 66 | # Be aware that this log type is a performance killer. 67 | # As of 5.1 you can enable the log at runtime! 68 | #general_log_file = /var/log/mysql/mysql.log 69 | #general_log = 1 70 | # 71 | # Error log - should be very few entries. 72 | # 73 | log_error = /var/log/mysql/error.log 74 | # 75 | # Here you can see queries with especially long duration 76 | #log_slow_queries = /var/log/mysql/mysql-slow.log 77 | #long_query_time = 2 78 | #log-queries-not-using-indexes 79 | # 80 | # The following can be used as easy to replay backup logs or for replication. 81 | # note: if you are setting up a replication slave, see README.Debian about 82 | # other settings you may need to change. 83 | #server-id = 1 84 | #log_bin = /var/log/mysql/mysql-bin.log 85 | expire_logs_days = 10 86 | max_binlog_size = 100M 87 | #binlog_do_db = include_database_name 88 | #binlog_ignore_db = include_database_name 89 | # 90 | # * InnoDB 91 | # 92 | # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. 93 | # Read the manual for more InnoDB related options. There are many! 94 | # 95 | # * Security Features 96 | # 97 | # Read the manual, too, if you want chroot! 98 | # chroot = /var/lib/mysql/ 99 | # 100 | # For generating SSL certificates I recommend the OpenSSL GUI "tinyca". 101 | # 102 | # ssl-ca=/etc/mysql/cacert.pem 103 | # ssl-cert=/etc/mysql/server-cert.pem 104 | # ssl-key=/etc/mysql/server-key.pem 105 | server-id = 1 106 | log_bin = /var/log/mysql/mysql-bin.log 107 | binlog_do_db = tyrell_corp 108 | -------------------------------------------------------------------------------- /0x14-mysql/4-mysql_configuration_replica: -------------------------------------------------------------------------------- 1 | # 2 | # The MySQL database server configuration file. 3 | # 4 | # You can copy this to one of: 5 | # - "/etc/mysql/my.cnf" to set global options, 6 | # - "~/.my.cnf" to set user-specific options. 7 | # 8 | # One can use all long options that the program supports. 9 | # Run program with --help to get a list of available options and with 10 | # --print-defaults to see which it would actually understand and use. 11 | # 12 | # For explanations see 13 | # http://dev.mysql.com/doc/mysql/en/server-system-variables.html 14 | 15 | # This will be passed to all mysql clients 16 | # It has been reported that passwords should be enclosed with ticks/quotes 17 | # escpecially if they contain "#" chars... 18 | # Remember to edit /etc/mysql/debian.cnf when changing the socket location. 19 | 20 | # Here is entries for some specific programs 21 | # The following values assume you have at least 32M ram 22 | 23 | [mysqld_safe] 24 | socket = /var/run/mysqld/mysqld.sock 25 | nice = 0 26 | 27 | [mysqld] 28 | # 29 | # * Basic Settings 30 | # 31 | user = mysql 32 | pid-file = /var/run/mysqld/mysqld.pid 33 | socket = /var/run/mysqld/mysqld.sock 34 | port = 3306 35 | basedir = /usr 36 | datadir = /var/lib/mysql 37 | tmpdir = /tmp 38 | lc-messages-dir = /usr/share/mysql 39 | skip-external-locking 40 | # 41 | # Instead of skip-networking the default is now to listen only on 42 | # localhost which is more compatible and is not less secure. 43 | # bind-address = 127.0.0.1 44 | # 45 | # * Fine Tuning 46 | # 47 | key_buffer_size = 16M 48 | max_allowed_packet = 16M 49 | thread_stack = 192K 50 | thread_cache_size = 8 51 | # This replaces the startup script and checks MyISAM tables if needed 52 | # the first time they are touched 53 | myisam-recover-options = BACKUP 54 | #max_connections = 100 55 | #table_cache = 64 56 | #thread_concurrency = 10 57 | # 58 | # * Query Cache Configuration 59 | # 60 | query_cache_limit = 1M 61 | query_cache_size = 16M 62 | # 63 | # * Logging and Replication 64 | # 65 | # Both location gets rotated by the cronjob. 66 | # Be aware that this log type is a performance killer. 67 | # As of 5.1 you can enable the log at runtime! 68 | #general_log_file = /var/log/mysql/mysql.log 69 | #general_log = 1 70 | # 71 | # Error log - should be very few entries. 72 | # 73 | log_error = /var/log/mysql/error.log 74 | # 75 | # Here you can see queries with especially long duration 76 | #log_slow_queries = /var/log/mysql/mysql-slow.log 77 | #long_query_time = 2 78 | #log-queries-not-using-indexes 79 | # 80 | # The following can be used as easy to replay backup logs or for replication. 81 | # note: if you are setting up a replication slave, see README.Debian about 82 | # other settings you may need to change. 83 | #server-id = 1 84 | #log_bin = /var/log/mysql/mysql-bin.log 85 | expire_logs_days = 10 86 | max_binlog_size = 100M 87 | #binlog_do_db = include_database_name 88 | #binlog_ignore_db = include_database_name 89 | # 90 | # * InnoDB 91 | # 92 | # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. 93 | # Read the manual for more InnoDB related options. There are many! 94 | # 95 | # * Security Features 96 | # 97 | # Read the manual, too, if you want chroot! 98 | # chroot = /var/lib/mysql/ 99 | # 100 | # For generating SSL certificates I recommend the OpenSSL GUI "tinyca". 101 | # 102 | # ssl-ca=/etc/mysql/cacert.pem 103 | # ssl-cert=/etc/mysql/server-cert.pem 104 | # ssl-key=/etc/mysql/server-key.pem 105 | server-id = 2 106 | relay-log = /var/log/mysql/mysql-relay-bin.log 107 | log_bin = /var/log/mysql/mysql-bin.log 108 | binlog_do_db = tyrell_corp 109 | -------------------------------------------------------------------------------- /0x14-mysql/5-mysql_backup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # generates a MySQL dump and creates a compressed archive out of it 3 | 4 | mysqldump -u root -p"$1" --all-databases > backup.sql 5 | tar -czvf "$(date '+%d-%m-%Y').tar.gz" backup.sql 6 | -------------------------------------------------------------------------------- /0x14-mysql/README.md: -------------------------------------------------------------------------------- 1 | # MySQL 2 | 3 | ### Tasks 4 | 0. Install MySQL 5 | 1. Let us in! 6 | 2. If only you could see what I've seen with your eyes 7 | 3. Quite an experience to live in fear, isn't it? 8 | 4. Setup a Primary-Replica infrastructure using MySQL 9 | 5. MySQL backup 10 | 11 | -------------------------------------------------------------------------------- /0x15-api/0-gather_data_from_an_API.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A script that gathers data from an API. 3 | ''' 4 | import re 5 | import requests 6 | import sys 7 | 8 | 9 | API_URL = 'https://jsonplaceholder.typicode.com' 10 | '''The API's URL.''' 11 | 12 | 13 | if __name__ == '__main__': 14 | if len(sys.argv) > 1: 15 | if re.fullmatch(r'\d+', sys.argv[1]): 16 | id = int(sys.argv[1]) 17 | user_res = requests.get('{}/users/{}'.format(API_URL, id)).json() 18 | todos_res = requests.get('{}/todos'.format(API_URL)).json() 19 | user_name = user_res.get('name') 20 | todos = list(filter(lambda x: x.get('userId') == id, todos_res)) 21 | todos_done = list(filter(lambda x: x.get('completed'), todos)) 22 | print( 23 | 'Employee {} is done with tasks({}/{}):'.format( 24 | user_name, 25 | len(todos_done), 26 | len(todos) 27 | ) 28 | ) 29 | for todo_done in todos_done: 30 | print('\t {}'.format(todo_done.get('title'))) 31 | -------------------------------------------------------------------------------- /0x15-api/1-export_to_CSV.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A script that gathers data from an API and exports it to a CSV file. 3 | ''' 4 | import re 5 | import requests 6 | import sys 7 | 8 | 9 | API_URL = 'https://jsonplaceholder.typicode.com' 10 | '''The API's URL.''' 11 | 12 | 13 | if __name__ == '__main__': 14 | if len(sys.argv) > 1: 15 | if re.fullmatch(r'\d+', sys.argv[1]): 16 | id = int(sys.argv[1]) 17 | user_res = requests.get('{}/users/{}'.format(API_URL, id)).json() 18 | todos_res = requests.get('{}/todos'.format(API_URL)).json() 19 | user_name = user_res.get('username') 20 | todos = list(filter(lambda x: x.get('userId') == id, todos_res)) 21 | with open('{}.csv'.format(id), 'w') as file: 22 | for todo in todos: 23 | file.write( 24 | '"{}","{}","{}","{}"\n'.format( 25 | id, 26 | user_name, 27 | todo.get('completed'), 28 | todo.get('title') 29 | ) 30 | ) 31 | -------------------------------------------------------------------------------- /0x15-api/2-export_to_JSON.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A script that gathers data from an API and exports it to a CSV file. 3 | ''' 4 | import re 5 | import requests 6 | import sys 7 | 8 | 9 | API_URL = 'https://jsonplaceholder.typicode.com' 10 | '''The API's URL.''' 11 | 12 | 13 | if __name__ == '__main__': 14 | if len(sys.argv) > 1: 15 | if re.fullmatch(r'\d+', sys.argv[1]): 16 | id = int(sys.argv[1]) 17 | user_res = requests.get('{}/users/{}'.format(API_URL, id)).json() 18 | todos_res = requests.get('{}/todos'.format(API_URL)).json() 19 | user_name = user_res.get('username') 20 | todos = list(filter(lambda x: x.get('userId') == id, todos_res)) 21 | with open('{}.csv'.format(id), 'w') as file: 22 | for todo in todos: 23 | file.write( 24 | '"{}","{}","{}","{}"\n'.format( 25 | id, 26 | user_name, 27 | todo.get('completed'), 28 | todo.get('title') 29 | ) 30 | ) 31 | -------------------------------------------------------------------------------- /0x15-api/3-dictionary_of_list_of_dictionaries.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A script that gathers data from an API and exports it to a JSON file. 3 | ''' 4 | import json 5 | import requests 6 | 7 | 8 | API_URL = 'https://jsonplaceholder.typicode.com' 9 | '''The API's URL.''' 10 | 11 | 12 | if __name__ == '__main__': 13 | users_res = requests.get('{}/users'.format(API_URL)).json() 14 | todos_res = requests.get('{}/todos'.format(API_URL)).json() 15 | users_data = {} 16 | for user in users_res: 17 | id = user.get('id') 18 | user_name = user.get('username') 19 | todos = list(filter(lambda x: x.get('userId') == id, todos_res)) 20 | user_data = list(map( 21 | lambda x: { 22 | 'username': user_name, 23 | 'task': x.get('title'), 24 | 'completed': x.get('completed') 25 | }, 26 | todos 27 | )) 28 | users_data['{}'.format(id)] = user_data 29 | with open('todo_all_employees.json', 'w') as file: 30 | json.dump(users_data, file) 31 | -------------------------------------------------------------------------------- /0x15-api/README.md: -------------------------------------------------------------------------------- 1 | # API 2 | 3 | This project contains tasks for learning about how to consume RESTful APIs. 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. Gather data from an API
_**[0-gather_data_from_an_API.py](0-gather_data_from_an_API.py)**_ contains a Python script that uses this [REST API](https://jsonplaceholder.typicode.com/), and for a given employee ID, returns information about his/her TODO list progress. 8 | + Requirements: 9 | + You must use `urllib` or `requests` module. 10 | + The script must accept an integer as a parameter, which is the employee ID. 11 | + The script must display on the standard output the employee TODO list progress in this exact format: 12 | + First line: `Employee EMPLOYEE_NAME is done with tasks(NUMBER_OF_DONE_TASKS/TOTAL_NUMBER_OF_TASKS):` 13 | + `EMPLOYEE_NAME`: name of the employee. 14 | + `NUMBER_OF_DONE_TASKS`: number of completed tasks. 15 | + `TOTAL_NUMBER_OF_TASKS`: total number of tasks, which is the sum of completed and non-completed tasks. 16 | + Second and N next lines display the title of completed tasks: `TASK_TITLE` (with 1 tabulation and 1 space before the `TASK_TITLE`). 17 | 18 | + [x] 1. Export to CSV
_**[1-export_to_CSV.py](1-export_to_CSV.py)**_ contains a Python script that uses what was done in task #0 to export data in the CSV format. 19 | + Requirements: 20 | + Records all tasks that are owned by this employee. 21 | + Format must be: `"USER_ID","USERNAME","TASK_COMPLETED_STATUS","TASK_TITLE"`. 22 | + File name must be: `USER_ID.csv`. 23 | 24 | + [x] 2. Export to JSON
_**[2-export_to_JSON.py](2-export_to_JSON.py)**_ contains a Python script that uses what was done in task #0 to export data in the JSON format. 25 | + Requirements: 26 | + Records all tasks that are owned by this employee. 27 | + Format must be: `{ "USER_ID": [{"task": "TASK_TITLE", "completed": TASK_COMPLETED_STATUS, "username": "USERNAME"}, {"task": "TASK_TITLE", "completed": TASK_COMPLETED_STATUS, "username": "USERNAME"}, ... ]}`. 28 | + File name must be: `USER_ID.json`. 29 | 30 | + [x] 3. Dictionary of list of dictionaries
_**[3-dictionary_of_list_of_dictionaries.py](3-dictionary_of_list_of_dictionaries.py)**_ contains a Python script that uses what was done in task #0 to export data in the JSON format. 31 | + Requirements: 32 | + Records all tasks from all employees 33 | + Format must be: `{ "USER_ID": [ {"username": "USERNAME", "task": "TASK_TITLE", "completed": TASK_COMPLETED_STATUS}, {"username": "USERNAME", "task": "TASK_TITLE", "completed": TASK_COMPLETED_STATUS}, ... ], "USER_ID": [ {"username": "USERNAME", "task": "TASK_TITLE", "completed": TASK_COMPLETED_STATUS}, {"username": "USERNAME", "task": "TASK_TITLE", "completed": TASK_COMPLETED_STATUS}, ... ]}`. 34 | + File name must be: `todo_all_employees.json`. 35 | -------------------------------------------------------------------------------- /0x16-api_advanced/0-subs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A module containing functions for working with the Reddit API. 3 | ''' 4 | import requests 5 | 6 | 7 | BASE_URL = 'https://www.reddit.com' 8 | '''Reddit's base API URL. 9 | ''' 10 | 11 | 12 | def number_of_subscribers(subreddit): 13 | '''Retrieves the number of subscribers in a given subreddit. 14 | ''' 15 | api_headers = { 16 | 'Accept': 'application/json', 17 | 'User-Agent': ' '.join([ 18 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 19 | 'AppleWebKit/537.36 (KHTML, like Gecko)', 20 | 'Chrome/97.0.4692.71', 21 | 'Safari/537.36', 22 | 'Edg/97.0.1072.62' 23 | ]) 24 | } 25 | res = requests.get( 26 | '{}/r/{}/about/.json'.format(BASE_URL, subreddit), 27 | headers=api_headers, 28 | allow_redirects=False 29 | ) 30 | if res.status_code == 200: 31 | return res.json()['data']['subscribers'] 32 | return 0 33 | -------------------------------------------------------------------------------- /0x16-api_advanced/1-top_ten.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A module containing functions for working with the Reddit API. 3 | ''' 4 | import requests 5 | 6 | 7 | BASE_URL = 'https://www.reddit.com' 8 | '''Reddit's base API URL. 9 | ''' 10 | 11 | 12 | def top_ten(subreddit): 13 | '''Retrieves the title of the top ten posts from a given subreddit. 14 | ''' 15 | api_headers = { 16 | 'Accept': 'application/json', 17 | 'User-Agent': ' '.join([ 18 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 19 | 'AppleWebKit/537.36 (KHTML, like Gecko)', 20 | 'Chrome/97.0.4692.71', 21 | 'Safari/537.36', 22 | 'Edg/97.0.1072.62' 23 | ]) 24 | } 25 | sort = 'top' 26 | limit = 10 27 | res = requests.get( 28 | '{}/r/{}/.json?sort={}&limit={}'.format( 29 | BASE_URL, 30 | subreddit, 31 | sort, 32 | limit 33 | ), 34 | headers=api_headers, 35 | allow_redirects=False 36 | ) 37 | if res.status_code == 200: 38 | for post in res.json()['data']['children'][0:10]: 39 | print(post['data']['title']) 40 | else: 41 | print(None) 42 | -------------------------------------------------------------------------------- /0x16-api_advanced/100-count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A module containing functions for working with the Reddit API. 3 | ''' 4 | import requests 5 | 6 | 7 | def sort_histogram(histogram={}): 8 | '''Sorts and prints the given histogram. 9 | ''' 10 | histogram = list(filter(lambda kv: kv[1], histogram)) 11 | histogram_dict = {} 12 | for item in histogram: 13 | if item[0] in histogram_dict: 14 | histogram_dict[item[0]] += item[1] 15 | else: 16 | histogram_dict[item[0]] = item[1] 17 | histogram = list(histogram_dict.items()) 18 | histogram.sort( 19 | key=lambda kv: kv[0], 20 | reverse=False 21 | ) 22 | histogram.sort( 23 | key=lambda kv: kv[1], 24 | reverse=True 25 | ) 26 | res_str = '\n'.join(list(map( 27 | lambda kv: '{}: {}'.format(kv[0], kv[1]), 28 | histogram 29 | ))) 30 | if res_str: 31 | print(res_str) 32 | 33 | 34 | def count_words(subreddit, word_list, histogram=[], n=0, after=None): 35 | '''Counts the number of times each word in a given wordlist 36 | occurs in a given subreddit. 37 | ''' 38 | api_headers = { 39 | 'Accept': 'application/json', 40 | 'User-Agent': ' '.join([ 41 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 42 | 'AppleWebKit/537.36 (KHTML, like Gecko)', 43 | 'Chrome/97.0.4692.71', 44 | 'Safari/537.36', 45 | 'Edg/97.0.1072.62' 46 | ]) 47 | } 48 | sort = 'hot' 49 | limit = 30 50 | res = requests.get( 51 | '{}/r/{}/.json?sort={}&limit={}&count={}&after={}'.format( 52 | 'https://www.reddit.com', 53 | subreddit, 54 | sort, 55 | limit, 56 | n, 57 | after if after else '' 58 | ), 59 | headers=api_headers, 60 | allow_redirects=False 61 | ) 62 | if not histogram: 63 | word_list = list(map(lambda word: word.lower(), word_list)) 64 | histogram = list(map(lambda word: (word, 0), word_list)) 65 | if res.status_code == 200: 66 | data = res.json()['data'] 67 | posts = data['children'] 68 | titles = list(map(lambda post: post['data']['title'], posts)) 69 | histogram = list(map( 70 | lambda kv: (kv[0], kv[1] + sum(list(map( 71 | lambda txt: txt.lower().split().count(kv[0]), 72 | titles 73 | )))), 74 | histogram 75 | )) 76 | if len(posts) >= limit and data['after']: 77 | count_words( 78 | subreddit, 79 | word_list, 80 | histogram, 81 | n + len(posts), 82 | data['after'] 83 | ) 84 | else: 85 | sort_histogram(histogram) 86 | else: 87 | return 88 | -------------------------------------------------------------------------------- /0x16-api_advanced/2-recurse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | '''A module containing functions for working with the Reddit API. 3 | ''' 4 | import requests 5 | 6 | 7 | BASE_URL = 'https://www.reddit.com' 8 | '''Reddit's base API URL. 9 | ''' 10 | 11 | 12 | def recurse(subreddit, hot_list=[], n=0, after=None): 13 | '''Retrieves a list of hot posts from a given subreddit. 14 | ''' 15 | api_headers = { 16 | 'Accept': 'application/json', 17 | 'User-Agent': ' '.join([ 18 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 19 | 'AppleWebKit/537.36 (KHTML, like Gecko)', 20 | 'Chrome/97.0.4692.71', 21 | 'Safari/537.36', 22 | 'Edg/97.0.1072.62' 23 | ]) 24 | } 25 | sort = 'hot' 26 | limit = 30 27 | res = requests.get( 28 | '{}/r/{}/.json?sort={}&limit={}&count={}&after={}'.format( 29 | BASE_URL, 30 | subreddit, 31 | sort, 32 | limit, 33 | n, 34 | after if after else '' 35 | ), 36 | headers=api_headers, 37 | allow_redirects=False 38 | ) 39 | if res.status_code == 200: 40 | data = res.json()['data'] 41 | posts = data['children'] 42 | count = len(posts) 43 | hot_list.extend(list(map(lambda x: x['data']['title'], posts))) 44 | if count >= limit and data['after']: 45 | return recurse(subreddit, hot_list, n + count, data['after']) 46 | else: 47 | return hot_list if hot_list else None 48 | else: 49 | return hot_list if hot_list else None 50 | -------------------------------------------------------------------------------- /0x16-api_advanced/README.md: -------------------------------------------------------------------------------- 1 | # API Advanced 2 | 3 | This project contains more tasks for learning how to consume RESTful APIs. 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. How many subs?
_**[0-subs.py](0-subs.py)**_ contains a Python function queries the [Reddit API](https://www.reddit.com/dev/api) and returns the number of subscribers (not active users, total subscribers) for a given subreddit. If an invalid subreddit is given, the function should return 0. 8 | + Hint: No authentication is necessary for most features of the Reddit API. If you’re getting errors related to Too Many Requests, ensure you’re setting a custom User-Agent. 9 | + Requirements: 10 | + Prototype: `def number_of_subscribers(subreddit)`. 11 | + If not a valid subreddit, return 0. 12 | + NOTE: Invalid subreddits may return a redirect to search results. Ensure that you are not following redirects. 13 | 14 | + [x] 1. Top Ten
_**[1-top_ten.py](1-top_ten.py)**_ contains a Python function queries the [Reddit API](https://www.reddit.com/dev/api) and prints the titles of the first 10 hot posts listed for a given subreddit. 15 | + Requirements: 16 | + Prototype: `def top_ten(subreddit)`. 17 | + If not a valid subreddit, print None. 18 | + NOTE: Invalid subreddits may return a redirect to search results. Ensure that you are not following redirects. 19 | 20 | + [x] 2. Recurse it!
_**[2-recurse.py](2-recurse.py)**_ contains a *recursive Python function* that queries the [Reddit API](https://www.reddit.com/dev/api) and returns a list containing the titles of all hot articles for a given subreddit. If no results are found for the given subreddit, the function should return None. 21 | + Hint: The Reddit API uses pagination for separating pages of responses. 22 | + Requirements: 23 | + Prototype: `def recurse(subreddit, hot_list=[])`. 24 | + Note: You may change the prototype, but it must be able to be called with just a subreddit supplied. AKA you can add a counter, but it must work without supplying a starting value in the main. 25 | + If not a valid subreddit, return None. 26 | + NOTE: Invalid subreddits may return a redirect to search results. Ensure that you are not following redirects. 27 | + Your code will NOT pass if you are using a loop and not recursively calling the function! This /can/ be done with a loop but the point is to use a recursive function. :) 28 | 29 | + [x] 3. Count it!
_**[100-count.py](100-count.py)**_ contains a *recursive Python function* that queries the Reddit API, parses the title of all hot articles, and prints a sorted count of given keywords (case-insensitive, delimited by spaces. `Javascript` should count as `javascript`, but `java` should not). 30 | + Requirements: 31 | + Prototype: `def count_words(subreddit, word_list)`. 32 | + Note: You may change the prototype, but it must be able to be called with just a subreddit supplied and a list of keywords. AKA you can add a counter or anything else, but the function must work without supplying a starting value in the main. 33 | + If `word_list` contains the same word (case-insensitive), the final count should be the sum of each duplicate (example below with `java`). 34 | + Results should be printed in descending order, by the count, and if the count is the same for separate keywords, they should then be sorted alphabetically (ascending, from A to Z). Words with no matches should be skipped and not printed. Words must be printed in lowercase. 35 | + Results are based on the number of times a keyword appears, not titles it appears in. `java java java` counts as 3 separate occurrences of `java`. 36 | + To make life easier, `java.` or `java!` or `java_` should not count as `java`. 37 | + If no posts match or the subreddit is invalid, print nothing. 38 | + NOTE: Invalid subreddits may return a redirect to search results. Ensure that you are NOT following redirects. 39 | + Your code will NOT pass if you are using a loop and not recursively calling the function! This /can/ be done with a loop but the point is to use a recursive function. :) 40 | -------------------------------------------------------------------------------- /0x17-web_stack_debugging_3/0-strace_is_your_friend.pp: -------------------------------------------------------------------------------- 1 | # Fixes a faulty wordpress site 2 | exec { 'fix-wordpress': 3 | command => 'bash -c "sed -i s/class-wp-locale.phpp/class-wp-locale.php/ \ 4 | /var/www/html/wp-settings.php; service apache2 restart"', 5 | path => '/usr/bin:/usr/sbin:/bin' 6 | } 7 | -------------------------------------------------------------------------------- /0x17-web_stack_debugging_3/README.md: -------------------------------------------------------------------------------- 1 | # Web Stack Debugging 2 | 3 | This project contains tasks for learning about how to debug web stacks. 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. Strace is your friend
_**[0-strace_is_your_friend.pp](0-strace_is_your_friend.pp)**_ contains a Puppet manifest that fixes a faulty server. 8 | + **Info**: 9 | + Using `strace`, find out why Apache is returning a 500 error. Once you find the issue, fix it and then automate it using Puppet (instead of using Bash as you were previously doing). 10 | + **HINT:** 11 | + `strace` can attach to a current running process. 12 | + You can use [tmux](https://www.hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/) to run [strace](https://strace.io/) in one window and `curl` in another one. 13 | -------------------------------------------------------------------------------- /0x18-webstack_monitoring/2-setup_datadog: -------------------------------------------------------------------------------- 1 | s6p-kzw-9t6 2 | -------------------------------------------------------------------------------- /0x18-webstack_monitoring/README.md: -------------------------------------------------------------------------------- 1 | # Webstack Monitoring 2 | 3 | This project contains some tasks for learning how to setup monitoring for a webstack on a server using **DATADOG**. 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. Sign up for Datadog and install datadog-agent 8 | + Head to [https://www.datadoghq.com/](https://www.datadoghq.com/) and sign up for a free `Datadog` account. When signing up, you'll have the option of selecting statistics from your current stack that `Datadog` can monitor for you. Once you have an account set up, follow the instructions given on the website to install the `Datadog` agent. 9 | + Sign up for Datadog - **Please make sure you are using the US website of Datagog (.com)**. 10 | + Install `datadog-agent` on `web-01`. 11 | + Create an `application key`. 12 | + Copy-paste in your Intranet user profile ([here](https://alx-intranet.hbtn.io/users/my_profile)) your DataDog `API key` and your DataDog `application key`. 13 | + Your server `web-01` should be visible in Datadog under the host name `XX-web-01` 14 | + You can validate it by using this [API](https://docs.datadoghq.com/api/latest/hosts/). 15 | + If needed, you will need to update the hostname of your server. 16 | 17 | + [x] 1. Monitor some metrics 18 | + Among the litany of data your monitoring service can report to you are system metrics. You can use these metrics to determine statistics such as reads/writes per second, which can help your company determine if/how they should scale. Set up some `monitors` within the `Datadog` dashboard to monitor and alert you of a few. You can read about the various system metrics that you can monitor here: [System Check](https://docs.datadoghq.com/integrations/system/). 19 | ![A monitor form on DataDog](Task_1.png) 20 | + Set up a monitor that checks the number of read requests issued to the device per second. 21 | + Set up a monitor that checks the number of write requests issued to the device per second. 22 | 23 | + [x] 2. Create a dashboard
_**[2-setup_datadog](2-setup_datadog)**_ contains the id of a dashboard with different metrics displayed in order to get a few different visualizations. 24 | + Create a new `dashboard`. 25 | + Add at least 4 `widgets` to your dashboard. They can be of any type and monitor whatever you'd like. 26 | ![A dashboard on DataDog](Task_2.png) 27 | + Create the answer file [`2-setup_datadog`](2-setup_datadog) which has the `dashboard_id` on the first line. **Note:** in order to get the id of your dashboard, you may need to use [Datadog's API](https://docs.datadoghq.com/api/latest/dashboards/#get-all-dashboards). 28 | -------------------------------------------------------------------------------- /0x18-webstack_monitoring/Task_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x18-webstack_monitoring/Task_1.png -------------------------------------------------------------------------------- /0x18-webstack_monitoring/Task_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x18-webstack_monitoring/Task_2.png -------------------------------------------------------------------------------- /0x19-postmortem/Blog_Post.md: -------------------------------------------------------------------------------- 1 | # Postmortem 2 | 3 | ![Flogging a dead horse](post-mortem-meetings.jpg) 4 | 5 | ## Issue Summary 6 | 7 | We had just released a new feature to our recently launched Ruby on Rails site that we had our first intake of users complaining about the site. 5 minutes after we performed a feature update, we started receiving emails from our users talking about "they can't sign in or sign up to our platform". It was quite surprising to us because we knew it worked on our machines and it worked before. About 127 of such emails came to our inbox. It was an avalanche of emails. Knowing how hard it can be to attract and keep users, we couldn't afford to lose 127 of our users in that way and decided to take a closer look at the problem. We cloned our site's repository from GitBug, followed the installation instructions on the README and to our surprise the site couldn't startup. It wasn't long before we realized that the cause of the problem was failing to update the requirements for our project. The site was malfunctioning from 9:55 AM GMT+1 to 11:20 AM GMT+1. 8 | 9 | ## Timeline 10 | 11 | + 05-02-2022 9:55 AM GMT+1 - A customer complained that they couldn't sign in to the site. 12 | + 05-02-2022 10:20 AM GMT+1 - Winus, one of our backend developers, experienced the same issues our customers reported. 13 | + 05-02-2022 10:35 AM GMT+1 - We investigated the controllers and the views for inconsistencies. 14 | + 05-02-2022 10:40 AM GMT+1 - We assumed the bcrypt (one of our site's dependencies) gem being used was either at fault or used incorrectly because the error message on the site showed that the bcrypt gem was raising an error over an invalid hash. 15 | + 05-02-2022 10:42 AM GMT+1 - We checked that the views might not be binding the form fields to the right model fields, which later turned out to be false. 16 | + 05-02-2022 10:45 AM GMT+1 - We were misled by thinking that our controllers might be creating a different hash for a valid password of the site's admin. 17 | + 05-02-2022 10:50 AM GMT+1 - Winus thought the issue might have been that the password was not properly hashed. 18 | + 05-02-2022 11:00 AM GMT+1 - The incident was escalated to the backend development team. 19 | + 05-02-2022 11:20 AM GMT+1 - The incident was resolved by updating the requirements (the bcrypt gem version) for the backend server. 20 | 21 | ## Root Cause And Resolution 22 | 23 | The version of the bcrypt gem we used was outdated. It was raising an error over a hash that was clearly valid and matched what was stored in the database. It could be that the hash we were creating was not supported by the version of bcrypt we had installed. Winus fixed the issue by manually updating the version of bcrypt in the Gemfile.lock file to a more recent version and reinstalling the required gems, and it worked like a charm. 24 | 25 | ## Corrective And Preventative Measures 26 | 27 | + Setup a continuous integration pipeline to run a build on each pull request branch. This would ensure that builds are passing in the pull request branch before it is merged with the deployment branch. 28 | + Setup a monitoring system for the database and application servers to keep track of any issue that may occur. 29 | + Develop tests that need to be passed for each new feature and those tests should be passing before they are merged with the deployment branch. 30 | -------------------------------------------------------------------------------- /0x19-postmortem/README.md: -------------------------------------------------------------------------------- 1 | # Postmortem 2 | 3 | This project contains tasks for learning about writing a postmortem. 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. My first postmortem
_**[Blog_Post.md](Blog_Post.md)**_ contains a blog post that meets the following requirements: 8 | + **INFO:** 9 | + Using one of the web stack debugging project issue or an outage you have personally face, write a postmortem. Most of you will never have faced an outage, so just get creative and invent your own :) 10 | + While postmortem format can vary, stick to this one so that you can get properly reviewed by your peers. 11 | + **Requirements:** 12 | + Issue Summary (that is often what executives will read) must contain: 13 | + Duration of the outage with start and end times (including timezone). 14 | + What was the impact? (What service was down/slow? What were user experiencing? How many % of the users were affected?) 15 | + What was the root cause? 16 | + Timeline (format bullet point, format: `time` - `keep it short, 1 or 2 sentences`) must contain: 17 | + When was the issue detected? 18 | + How was the issue detected (monitoring alert, an engineer noticed something, a customer complained…) 19 | + Actions taken (what parts of the system were investigated, what were the assumption on the root cause of the issue). 20 | + Misleading investigation/debugging paths that were taken. 21 | + Which team/individuals was the incident escalated to? 22 | + How the incident was resolved. 23 | + Root cause and resolution must contain: 24 | + Explain in detail what was causing the issue. 25 | + Explain in detail how the issue was fixed. 26 | + Corrective and preventative measures must contain: 27 | + What are the things that can be improved/fixed (broadly speaking) 28 | + A list of tasks to address the issue (be very specific, like a TODO, example: patch Nginx server, add monitoring on server memory…). 29 | + Be brief and straight to the point, between 400 to 600 words 30 | 31 | + [x] 1. Make people want to read your postmortem 32 | + We are constantly stormed by a quantity of information, it’s tough to get people to read you. 33 | + Make your post-mortem attractive by adding humour, a pretty diagram or anything that would catch your audience attention. 34 | -------------------------------------------------------------------------------- /0x19-postmortem/post-mortem-meetings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/0x19-postmortem/post-mortem-meetings.jpg -------------------------------------------------------------------------------- /0x1A-application_server/2-app_server-nginx_config: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | 5 | root /var/www/html; 6 | index index.html index.htm index.nginx-debian.html; 7 | 8 | server_name _; 9 | 10 | location / { 11 | try_files $uri $uri/ =404; 12 | } 13 | 14 | location /airbnb-onepage/ { 15 | proxy_pass http://localhost:5000; 16 | } 17 | 18 | if ($request_filename ~ redirect_me){ 19 | rewrite ^ https://sketchfab.com/bluepeno/models permanent; 20 | } 21 | 22 | error_page 404 /404.html; 23 | location = /404.html { 24 | root /var/www/error/; 25 | internal; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /0x1A-application_server/3-app_server-nginx_config: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | 5 | root /var/www/html; 6 | index index.html index.htm index.nginx-debian.html; 7 | 8 | server_name _; 9 | 10 | location / { 11 | try_files $uri $uri/ =404; 12 | } 13 | 14 | location /airbnb-onepage/ { 15 | proxy_pass http://localhost:5000; 16 | } 17 | 18 | location /airbnb-dynamic/ { 19 | proxy_pass http://localhost:5001/; 20 | } 21 | 22 | if ($request_filename ~ redirect_me){ 23 | rewrite ^ https://sketchfab.com/bluepeno/models permanent; 24 | } 25 | 26 | error_page 404 /404.html; 27 | location = /404.html { 28 | root /var/www/error/; 29 | internal; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /0x1A-application_server/4-app_server-nginx_config: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | 5 | root /var/www/html; 6 | index index.html index.htm index.nginx-debian.html; 7 | 8 | server_name _; 9 | 10 | location / { 11 | try_files $uri $uri/ =404; 12 | } 13 | 14 | location /airbnb-onepage/ { 15 | proxy_pass http://localhost:5000; 16 | } 17 | 18 | location /airbnb-dynamic/ { 19 | proxy_pass http://localhost:5001/; 20 | } 21 | 22 | location /api/ { 23 | proxy_pass http://localhost:5002; 24 | } 25 | 26 | if ($request_filename ~ redirect_me){ 27 | rewrite ^ https://sketchfab.com/bluepeno/models permanent; 28 | } 29 | 30 | error_page 404 /404.html; 31 | location = /404.html { 32 | root /var/www/error/; 33 | internal; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /0x1A-application_server/4-reload_gunicorn_no_downtime: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Gracefully reloads Gunicorn 3 | systemctl status gunicorn | grep -oE 'Main PID: [0-9]+' | cut -d ' ' -f3 | xargs kill -HUP 4 | -------------------------------------------------------------------------------- /0x1A-application_server/5-app_server-nginx_config: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | 5 | root /var/www/html; 6 | index index.html index.htm index.nginx-debian.html; 7 | 8 | server_name _; 9 | 10 | location / { 11 | proxy_pass http://localhost:5003/2-hbnb; 12 | } 13 | 14 | location /static/ { 15 | # rewrite ^(/static/[^?]*)\?.*$ $1 last; 16 | alias /home/ubuntu/AirBnB_clone_v4/web_dynamic/static/; 17 | try_files $uri $uri/ =404; 18 | } 19 | 20 | location /airbnb-onepage/ { 21 | proxy_pass http://localhost:5000; 22 | } 23 | 24 | location /airbnb-dynamic/ { 25 | proxy_pass http://localhost:5001/; 26 | } 27 | 28 | location /api/ { 29 | proxy_pass http://localhost:5002; 30 | } 31 | 32 | if ($request_filename ~ redirect_me){ 33 | rewrite ^ https://sketchfab.com/bluepeno/models permanent; 34 | } 35 | 36 | error_page 404 /404.html; 37 | location = /404.html { 38 | root /var/www/error/; 39 | internal; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /0x1A-application_server/README.md: -------------------------------------------------------------------------------- 1 | # Application Server 2 | 3 | This project contains tasks for learning how to configure a web server (nginx) with an application server (Gunicorn). 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. Set up development with Python
Let’s serve what you built for [AirBnB clone v2 - Web framework](https://github.com/B3zaleel/AirBnB_clone_v2) on `web-01`. This task is an exercise in setting up your development environment, which is used for testing and debugging your code before deploying it to production. 8 | + Requirements: 9 | + Make sure that task #3 of your [SSH project](../0x0B-ssh/README.md) is completed for `web-01`. The checker will connect to your servers. 10 | + Git clone your `AirBnB_clone_v2` on your `web-01` server. 11 | + Configure the file `web_flask/0-hello_route.py` to serve its content from the route `/airbnb-onepage/` on port `5000`. 12 | + Your Flask application object must be named `app` (This will allow us to run and check your code). 13 | 14 | + [x] 1. Set up production with Gunicorn
Now that you have your development environment set up, let’s get your production application server set up with `Gunicorn` on `web-01`, port `5000`. You’ll need to install `Gunicorn` and any libraries required by your application. Your `Flask` application object will serve as a [WSGI](https://www.fullstackpython.com/wsgi-servers.html) entry point into your application. This will be your production environment. As you can see we want the production and development of your application to use the same port, so the conditions for serving your dynamic content are the same in both environments. 15 | + Requirements: 16 | + Install `Gunicorn` and any other libraries required by your application. 17 | + The Flask application object should be called `app`. (This will allow us to run and check your code). 18 | + You will serve the same content from the same route as in the previous task. You can verify that it’s working by binding a `Gunicorn` instance to localhost listening on port `5000` with your application object as the entry point. 19 | + In order to check your code, the checker will bind a `Gunicorn` instance to port `6000`, so make sure nothing is listening on that port. 20 | 21 | + [x] 2. Serve a page with Nginx
Building on your work in the previous tasks, configure Nginx to serve your page from the route `/airbnb-onepage/`. 22 | + Requirements: 23 | + `Nginx` must serve this page both locally and on its public IP on port `80`. 24 | + `Nginx` should proxy requests to the process listening on port 5000. 25 | + Include your `Nginx` config file as `2-app_server-nginx_config`. 26 | + Notes: 27 | + In order to test this you’ll have to spin up either your production or development application server (listening on port `5000`). 28 | + In an actual production environment the application server will be configured to start upon startup in a system initialization script. This will be covered in the advanced tasks. 29 | + You will probably need to `reboot` your server (by using the command `sudo reboot`) to have Nginx publicly accessible. 30 | 31 | + [x] 3. Add a route with query parameters
Building on what you did in the previous tasks, let’s expand our web application by adding another service for `Gunicorn` to handle. In `AirBnB_clone_v2/web_flask/6-number_odd_or_even`, the route `/number_odd_or_even/` should already be defined to render a page telling you whether an integer is odd or even. You’ll need to configure `Nginx` to proxy HTTP requests to the route `/airbnb-dynamic/number_odd_or_even/(any integer)` to a `Gunicorn` instance listening on port `5001`. The key to this exercise is getting `Nginx` configured to proxy requests to processes listening on two different ports. You are not expected to keep your application server processes running. If you want to know how to run multiple instances of `Gunicorn` without having multiple terminals open, see tips below. 32 | + Requirements: 33 | + `Nginx` must serve this page both locally and on its public IP on port `80`. 34 | + `Nginx` should proxy requests to the route `/airbnb-dynamic/number_odd_or_even/(any integer)` the process listening on port `5001`. 35 | + Include your `Nginx` config file as `3-app_server-nginx_config`. 36 | + Tips: 37 | + Check out these articles/docs for clues on how to configure `Nginx`: [Understanding Nginx Server and Location Block Selection Algorithms](https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms#matching-location-blocks), [Understanding Nginx Location Blocks Rewrite Rules](http://blog.pixelastic.com/2013/09/27/understanding-nginx-location-blocks-rewrite-rules/), [Nginx Reverse Proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/#). 38 | + In order to spin up a `Gunicorn` instance as a detached process you can use the terminal multiplexer utility `tmux`. Enter the command `tmux new-session -d 'gunicorn --bind 0.0.0.0:5001 web_flask.6-number_odd_or_even:app'` and if successful you should see no output to the screen. You can verify that the process has been created by running `pgrep gunicorn` to see its PID. Once you’re ready to end the process you can either run `tmux a` to reattach to the processes, or you can run `kill ` to terminate the background process by ID. 39 | 40 | + [x] 4. Let's do this for your API
Let’s serve what you built for [AirBnB clone v3 - RESTful API](https://github.com/B3zaleel/AirBnB_clone_v3) on `web-01`. 41 | + Requirements: 42 | + Git clone your `AirBnB_clone_v3`. 43 | + Setup `Nginx` so that the route `/api/` points to a `Gunicorn` instance listening on port `5002`. 44 | + `Nginx` must serve this page both locally and on its public IP on port `80`. 45 | + To test your setup you should bind `Gunicorn` to `api/v1/app.py`. 46 | + It may be helpful to import your data (and environment variables) from [this project](https://github.com/B3zaleel/AirBnB_clone_v2). 47 | + Upload your `Nginx` config file as `4-app_server-nginx_config`. 48 | 49 | + [x] 5. Serve your AirBnB clone
Let’s serve what you built for [AirBnB clone - Web dynamic](https://github.com/B3zaleel/AirBnB_clone_v4) on `web-01`. 50 | + Requirements: 51 | + Git clone your [AirBnB_clone_v4](https://github.com/B3zaleel/AirBnB_clone_v4) 52 | + Your `Gunicorn` instance should serve content from web_dynamic/2-hbnb.py on port `5003`. 53 | + Setup `Nginx` so that the route `/` points to your `Gunicorn` instance. 54 | + Setup `Nginx` so that it properly serves the static assets found in `web_dynamic/static/` (this is essential for your page to render properly). 55 | + For your website to be fully functional, you will need to reconfigure `web_dynamic/static/scripts/2-hbnb.js` to the correct IP. 56 | + `Nginx` must serve this page both locally and on its public IP and port `5003`. 57 | + Make sure to pull up your Developer Tools on your favorite browser to verify that you have no errors. 58 | + Upload your `Nginx` config as `5-app_server-nginx_config`. 59 | 60 | + [x] 6. Deploy it!
Once you’ve got your application server configured, you want to set it up to run by default when Linux is booted. This way when your server inevitably requires downtime (you have to shut it down or restart it for one reason or another), your `Gunicorn` process(es) will start up as part of the system initialization process, freeing you from having to manually restart them. For this we will use `systemd`. You can read more about `systemd` in the documentation posted at the top of this project but to put it succinctly, it is a system initialization daemon for the Linux OS (amongst other things). For this task you will write a `systemd` script which will start your application server for you. As mentioned in the video at the top of the project, you do not need to create a Unix socket to bind the process to. 61 | + Requirements: 62 | + Write a `systemd` script which starts a `Gunicorn` process to serve the same content as the previous task (`web_dynamic/2-hbnb.py`). 63 | + The `Gunicorn` process should spawn 3 worker processes. 64 | + The process should log errors in `/tmp/airbnb-error.log`. 65 | + The process should log access in `/tmp/airbnb-access.log`. 66 | + The process should be bound to port `5003`. 67 | + Your `systemd` script should be stored in the appropriate directory on `web-01`. 68 | + Make sure that you start the systemd service and leave it running. 69 | + Upload `gunicorn.service` to GitHub. 70 | 71 | + [x] 7. No service interruption
72 | One of the most important metrics for any Internet-based business is its uptime. It is the percentage of the time over a given period that the service/product is accessible to customers. Let’s pick the example of Amazon.com, for every minute of downtime (which is the opposite of uptime), [it costs the company $2M](https://storageservers.wordpress.com/2016/03/14/amazon-downtime-costs-2-million-loss-per-minute/). Yet, application servers often need to restart to update with the new version of the code or new configuration, when doing this operation, an application server cannot serve traffic, which meant downtime. 73 | 74 | To avoid this; application servers are designed with a master/workers infrastructure. The master is in charge of: 75 | + Receiving requests 76 | + Managing workers (starting, stopping) 77 | + Distributing requests to workers 78 | Workers are the actual ones processing the query by generation dynamic content by processing the application code. 79 | 80 | To update an application without downtime, the master will proceed with a progressive rollout of the update. It will gracefully shut down some workers ( meaning that it will tell workers to finish processing the request they are working on, but will not send them new requests, once the worker is done, it’s will be shutdown) and start new ones with the new application code or configuration, then move on to the other old workers until it has renewed the whole pool. 81 | 82 | Write a simple Bash script to reload Gunicorn in a graceful way. This script should be stored in the file [4-reload_gunicorn_no_downtime](4-reload_gunicorn_no_downtime). 83 | -------------------------------------------------------------------------------- /0x1A-application_server/gunicorn.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=gunicorn.service - AirBnB clone by B3zaleel run with Gunicorn. 3 | After=network.target 4 | 5 | [Service] 6 | User=ubuntu 7 | Group=www-data 8 | WorkingDirectory=/home/ubuntu/AirBnB_clone_v4/ 9 | Environment=HBNB_MYSQL_USER=hbnb_dev 10 | Environment=HBNB_MYSQL_PWD=hbnb_dev_pwd 11 | Environment=HBNB_MYSQL_HOST=localhost 12 | Environment=HBNB_MYSQL_DB=hbnb_dev_db 13 | Environment=HBNB_TYPE_STORAGE=db 14 | Environment=HBNB_ENV=dev 15 | ExecStart=/usr/bin/gunicorn --workers 3 --error-logfile /tmp/airbnb-error.log --access-logfile /tmp/airbnb-access.log --bind 0.0.0.0:5003 web_dynamic.2-hbnb:app 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /0x1B-web_stack_debugging_4/0-the_sky_is_the_limit_not.pp: -------------------------------------------------------------------------------- 1 | # Fixes an nginx site that can't handle multiple concurrent requests 2 | exec { 'fix--for-nginx': 3 | command => "bash -c \"sed -iE 's/^ULIMIT=.*/ULIMIT=\\\"-n 8192\\\"/' \ 4 | /etc/default/nginx; service nginx restart\"", 5 | path => '/usr/bin:/usr/sbin:/bin' 6 | } 7 | -------------------------------------------------------------------------------- /0x1B-web_stack_debugging_4/1-user_limit.pp: -------------------------------------------------------------------------------- 1 | # Changes the limitations on the holberton user 2 | exec { 'change-os-configuration-for-holberton-user': 3 | command => "bash -c \"sed -iE 's/^holberton hard nofile \ 4 | 5/holberton hard nofile 88888/' /etc/security/limits.conf; \ 5 | sed -iE 's/^holberton soft nofile \ 6 | 4/holberton soft nofile 88888/' /etc/security/limits.conf\"", 7 | path => '/usr/bin:/usr/sbin:/bin' 8 | } 9 | -------------------------------------------------------------------------------- /0x1B-web_stack_debugging_4/README.md: -------------------------------------------------------------------------------- 1 | # Web Stack Debugging 2 | 3 | This project contains tasks for learning about how to debug web stacks. 4 | 5 | ## Tasks To Complete 6 | 7 | + [x] 0. Sky is the limit, let's bring that limit higher
_**[0-the_sky_is_the_limit_not.pp](0-the_sky_is_the_limit_not.pp)**_ contains a Puppet manifest that improves the capabilities of an Nginx server. 8 | + Info: 9 | + In this web stack debugging task, we are testing how well our web server setup featuring Nginx is doing under pressure and it turns out it’s not doing well: we are getting a huge amount of failed requests. 10 | + For the benchmarking, we are using ApacheBench which is a quite popular tool in the industry. It allows you to simulate HTTP requests to a web server. In this case, I will make 2000 requests to my server with 100 requests at a time. We can see that 943 requests failed, let’s fix our stack so that we get to 0, and remember that when something is going wrong, logs are your best friends! 11 | 12 | + [x] 1. User limit
_**[1-user_limit.pp](1-user_limit.pp)**_ contains a Puppet manifest that changes the OS configuration so that it is possible to login with the `holberton` user and open a file without any error message. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##Shell Scripting Basics Exercises 2 | 3 | Exercise 0: pwd === print working directory 4 | 5 | Exercise 1: ls === list directory contents 6 | 7 | Exercise 2: cd === change directory 8 | 9 | Exercise 3: ls -l === list directory contents in long form 10 | 11 | Exercise 4: ls -la === list directory contents in long form, including hidden files 12 | 13 | Exercise 5: ls -la Note: Are files inherently ordered? 14 | 15 | Exercise 6: mkdir /tmp/my_first_directory Create a my_first_directory directory inside the tmp directory 16 | 17 | Exercise 7: mv /tmp/betty /tmp/my_first_directory/betty Move file betty, which is located inside the tmp directory, to the my_first_directory directory, which is also located inside the tmp directory. This exercise required some dir traversing. 18 | 19 | Exercise 8: rm /tmp/my_first_directory/betty Remove file betty located in tmp/my_first_directory directory. 20 | 21 | Exercise 9: rmdir /tmp/my_first_directory Remove directory my_first_directory located in directory tmp. 22 | 23 | Exercise 10: cd - Change directory to the previous directory you were in. 24 | 25 | Exercise 11: ls -la . .. /boot List all files/directories, including hidden files/directories, from 3 separate directories: current directory, parent of working directory, and /boot directory. The ls command allows multiple directories to be listed separated by spaces. 26 | 27 | Exercise 12: file /tmp/iamafile Prints the type of file iamafile. 28 | 29 | Exercise 13: ln -s /bin/ls ls Create a symbolic link named ls for /bin/ls 30 | 31 | Exercise 14: cp -u *.html .. Copy all html files from the current directory to the parent directory, but only copy files that didn't exist in the parent directory or are newer versions than the ones that already exist in the parent directory. The -u option didn't show on the terminal manual page. The -u option copies the file into the directory if its a newer version. If the file doesn't exist in the directory, it will copy over. The -n option works for copying files that don't exist in the parent directory, but it doesn't check if the file is a newer version or not. 32 | 33 | Exercise 15: mv [[:upper:]]* /tmp/u Move all files that begin with a capital letter to /tmp/u 34 | 35 | Exercise 16: rm *~ Deletes all files in the current directory that end with a ~ 36 | 37 | Exercise 17: mkdir -p welcome/to/school Create directory welcome in current directory. Create directory to inside directory welcome. Create directory school inside directory to. The -p option creates any intermediate directories in the path argument. 38 | 39 | Exercise 18: ls -pam List all files and directories of the current directory, separated by commas. Directory names should end with a /. The listing should be alph ordered, except for dot (.) or dot dot (..), which should be listed at the beginning. The -a option is to show any hidden files. The -p option writes a / at the end of directory names. The -m option streams the output, separating each listing with commas. 40 | 41 | Exercise 19: 0 string SCHOOL School data !:mime School Create a magic file called school.mgc that can be used with the command file to detect School data files. School data files always contain "SCHOOL" at offset 0. 42 | This exercise was much different from the previous exercises. From what I understand, the magic file is used to detect patterns in files and will give a specified output depending on a matching pattern. The first argument is a number representing the offset. The second argument is the data type you are searching for. In our case, it is a string. The third argument is the data you are searching for. In our case, "SCHOOL", which we specified as a string in the second argument. The fourth argument is the message you want to output on match. If the search matches, it will output this message. The last argument is separated by a line. Since the fourth argument can be long and contain multiple strings, we separate the fourth and fifth arguments with this new line. This last argument can be multiple different things. In this case, a MIME type. According to bash manual, a "MIME type is given on a separate line, which must be the next non-blank or comment line after the magic line that identifies the file type". I knew to search for a MIME type because the example provided: $ file --mime-type -m holberton.mgc * The above returns message "School" when matching a MIME ?? Not exactly sure, but this is what I can tell from what I've tested out and can see from the output and examples. $ file -m school.mgc * The above will return message "SCHOOL data" for any offset 0 "School" matches. A cool thing to note is that the file command is compiling and running the magic file. So there is no need to compile to magic "permanently". NOTE: Compiling a magic source file: $ file -C -m .mgc This produces the compiled magic file. $ file -i -m .mgc * This allows you to use the compiled file by specifying its name using the -m switch again. 43 | -------------------------------------------------------------------------------- /attack_is_the_best_defense/0-sniffing: -------------------------------------------------------------------------------- 1 | mypassword9898! 2 | -------------------------------------------------------------------------------- /attack_is_the_best_defense/1-dictionary_attack: -------------------------------------------------------------------------------- 1 | password123 2 | -------------------------------------------------------------------------------- /attack_is_the_best_defense/README.md: -------------------------------------------------------------------------------- 1 | # Attack is the best defense 2 | 3 | ### Tasks 4 | 0. ARP spoofing and sniffing unencrypted traffic 5 | 1. Dictionary attack 6 | 7 | -------------------------------------------------------------------------------- /command_line_for_the_win/0-first_9_tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/command_line_for_the_win/0-first_9_tasks.png -------------------------------------------------------------------------------- /command_line_for_the_win/1-next_9_tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/command_line_for_the_win/1-next_9_tasks.png -------------------------------------------------------------------------------- /command_line_for_the_win/2-next_9-tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teddy004/alx-system_engineering-devops/cea8c3f89c541452750d9911499811aa85fc06d7/command_line_for_the_win/2-next_9-tasks.png -------------------------------------------------------------------------------- /command_line_for_the_win/README.md: -------------------------------------------------------------------------------- 1 | # Command Line For The Win 2 | 3 | This project contains solutions to some of the bash command challenges at [cmdchallenge](https://cmdchallenge.com/). See [Solutions](Solutions.md). 4 | 5 | ## Tasks to Complete 6 | 7 | + 1. [x] First 九 tasks
**_[0-first_9_tasks.png](0-first_9_tasks.png)_** Shows the completion of the first 9 tasks. 8 | + 1. [x] Reach חי completed tasks
**_[1-next_9_tasks.png](1-next_9_tasks.png)_** Shows the completion of the next 9 (the first 18) tasks. 9 | + 2. [x] Reach the perfect cube, 27
**_[2-next_9_tasks.png](2-next_9_tasks.png)_** Shows the completion of the next 9 (the first 27) tasks. 10 | -------------------------------------------------------------------------------- /command_line_for_the_win/Solutions.md: -------------------------------------------------------------------------------- 1 | # Solutions to the CMD Challenge 2 | 3 | + 1 -> hello_world
Your first challenge is to print "hello world" on the terminal in a single command. 4 | ```powershell 5 | echo 'hello world' 6 | ``` 7 | + 2 -> current_working_directory
Print the current working directory. 8 | ```powershell 9 | pwd 10 | ``` 11 | + 3 -> list_files
List names of all the files in the current directory, one file per line. 12 | ```powershell 13 | find -type f -regex ".*" -printf "%f\n" 14 | ``` 15 | + 4 -> foo
16 | ```powershell 17 | ``` 18 | + 5 -> foo
19 | ```powershell 20 | ``` 21 | + 6 -> foo
22 | ```powershell 23 | ``` 24 | + 7 -> foo
25 | ```powershell 26 | ``` 27 | + 8 -> foo
28 | ```powershell 29 | ``` 30 | + 9 -> foo
31 | ```powershell 32 | ``` 33 | + 10 -> foo
34 | ```powershell 35 | ``` 36 | + 11 -> foo
37 | ```powershell 38 | ``` 39 | + 12 -> foo
40 | ```powershell 41 | ``` 42 | + 13 -> foo
43 | ```powershell 44 | ``` 45 | + 14 -> search_for_files_containing_string
Print all files in the current directory, one per line (not the path, just the filename) that contain the string "500". 46 | ```powershell 47 | grep -sl 500 * .* 48 | ``` 49 | + 15 ->
Print the relative file paths, one path per line for all filenames that start with "access.log" in the current directory. 50 | ``` 51 | find -type f -regex '.*/access.log.*' 52 | ``` 53 | + 16 -> search_for_string_in_files_recursive
Print all matching lines (without the filename or the file path) in all files under the current directory that start with "access.log" that contain the string "500". 54 | ```powershell 55 | cat `find -type f -regex '.*/access.log.*' | tr \n ' '` | grep 500 56 | ``` 57 | + 17 -> extract_ip_addresses
Extract all IP addresses from files that start with "access.log" printing one IP address per line. 58 | ```powershell 59 | cat `find -type f -regex '.*/access.log.*' | tr '\n' ' '` | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' 60 | ``` 61 | + 18 -> count_files
Count the number of files in the current working directory. Print the number of files as a single integer. 62 | ```powershell 63 | find -type f -regex '.*' | wc -l 64 | ``` 65 | + 19 -> simple_sort
Print the contents of access.log sorted. 66 | ```powershell 67 | cat access.log | sort 68 | ``` 69 | + 20 -> count_string_in_line
Print the number of lines in access.log that contain the string "GET". 70 | ```powershell 71 | cat access.log | grep -o GET | wc -l 72 | ``` 73 | + 21 -> split_on_a_char
The file split-me.txt contains a list of numbers separated by a ; character.
Split the numbers on the ; character, one number per line. 74 | ```powershell 75 | cat split-me.txt | tr ';' "\n" 76 | ``` 77 | + 22 -> print_number_sequence
Print the numbers 1 to 100 separated by spaces. 78 | ```powershell 79 | echo {1..9} {1..9}{0..9} 100 80 | ``` 81 | + 23 -> replace_text_in_files
This challenge has text files (with a .txt extension) that contain the phrase "challenges are difficult". Delete this phrase from all text files recursively.
Note that some files are in subdirectories so you will need to search for them. 82 | ```powershell 83 | find -type f -regex '.*\.txt' -execdir bash -c 'cat "{}" | sed "s/challenges are difficult//g" > "{}"' \; 84 | ``` 85 | + 24 -> sum_all_numbers
The file sum-me.txt has a list of numbers, one per line. Print the sum of these numbers. 86 | ```powershell 87 | echo $((`cat sum-me.txt | tr '\n' '+' | rev | cut -c 2- | rev`)) 88 | ``` 89 | + 25 -> just_the_files
Print all files in the current directory recursively without the leading directory path. 90 | ```powershell 91 | find -type f -regex '.*' -execdir bash -c 'echo {} | cut -c 3-' \; 92 | ``` 93 | + 26 -> remove_extensions_from_files
Rename all files removing the extension from them in the current directory recursively. 94 | ```powershell 95 | find -type f -regex '.*' -execdir bash -c 'mv {} `echo {} | sed -r "s/\.[^.\S]+$//g"`' \; 96 | ``` 97 | + 27 -> replace_spaces_in_filenames
The files in this challenge contain spaces. List all of the files (filenames only) in the current directory but replace all spaces with a '.' character. 98 | ```powershell 99 | find -type f -regex '.*' -execdir bash -c 'echo {} | sed -r "s/\s/./g" | cut -c 3-' \; 100 | ``` 101 | + 28 -> dirs_containing_files_with_extension
In this challenge there are some directories containing files with different extensions. Print all directories, one per line without duplicates that contain one or more files with a ".tf" extension. 102 | ```powershell 103 | find -type f -regex '.*\.tf$' -exec bash -c 'echo {} | grep -oE ".*/" | cut -c 3- | rev | cut -c 2- | rev' \; | sort | uniq 104 | ``` 105 | + 29 -> files_starting_with_a_number
There are a mix of files in this directory that start with letters and numbers. Print the filenames (just the filenames) of all files that start with a number recursively in the current directory. 106 | ```powershell 107 | find -type f -regex ".*" -printf "%f\n" | grep -E "^[0-9]" 108 | ``` 109 | + 30 -> print_nth_line
Print the 25th line of the file faces.txt 110 | ```powershell 111 | head -n 25 faces.txt | tail -n 1 112 | ``` 113 | + 31 -> reverse_readme
Print the lines of the file reverse-me.txt in this directory in reverse line order so that the last line is printed first and the first line is printed last. 114 | ```powershell 115 | cat reverse-me.txt 116 | ``` 117 | + 28 -> foo
118 | ```powershell 119 | ``` 120 | --------------------------------------------------------------------------------