* 2020-07-24
*** IPv6 #2: Generating IPv6 networks
**** DONE Lecture content
     CLOSED: [2020-07-30 목 00:43]
    - Objective/Problem that we are trying to solve:
      - You got one bigger prefix (the one that you get as a
        parameter) and you want to create a random subnetwork in it
    - Create a random /48 network within a prefix
      - Create a python script named *randomnet.py* that accepts 1
        parameter: *prefix*
      - The prefix must be an IPv6 network
      - The netmask of the prefix should be /48 or smaller (/48.../0)
      - Prefixes to be used for testing:
        - 2001:db8::/48
        - 2001:db8::/40
        - 2001:db8::/32
        - fd00::/8
      - Possible output:
        - 2001:db8:1231::/48
    - Optional
      - Allow to specify second parameter that gives the size of the subnetwork
* 2020-07-22
*** IPv6 #1: IPv6 address uniqueness
**** DONE Lecture content
     CLOSED: [2020-07-23 목 00:06]
    - Ensure Uniqueness
      - Every IPv6 address we register should REPRESENT a /48
      - We need to ensure that we don't register overlapping networks
      - Write a python script that checks whether two IPv6 networks are overlapping
        - *overlap.py ip1 ip2*
      - It should output "overlap" or "no overlap"
      - Use the following test IPv6 addresses:
        - 2001:db8::
        - 2001:db8:0:2::
        - 2001:db8:1::
      - Assume a netmask of /48 for all of them
      - Step 2: Make your script parse ipv6 networks (like
        2001:db8::/48 and 2001:db8::/64) ) and check whether they overlap
      - Make use of the python3 module *ipaddress*
* 2020-07-15
*** Django #7: Tutorial 6
**** DONE Lecture content
     CLOSED: [2020-07-22 수 22:25]
     - Environment like in Django 1 and Django 3
       - Ensure your nginx is working
       - Paste the URL of your Django server into the chat
       - Ensure you can reach the other Django servers
     - Follow steps on https://docs.djangoproject.com/en/3.0/intro/tutorial06/
*** Django #8: Tutorial 7
**** DONE Lecture content
     CLOSED: [2020-07-22 수 22:25]
     - Environment like in Django 1 and Django 3
       - Ensure your nginx is working
       - Paste the URL of your Django server into the chat
       - Ensure you can reach the other Django servers
     - Follow steps on https://docs.djangoproject.com/en/3.0/intro/tutorial07/
* 2020-07-13
*** Django #6: Tutorial 5
**** DONE Lecture content
     CLOSED: [2020-07-14 화 00:25]
     - Environment like in Django 1 and Django 3
       - Ensure your nginx is working
     - Follow steps on https://docs.djangoproject.com/en/3.0/intro/tutorial05/

* 2020-07-10
*** Django #5: Tutorial 4
**** DONE Lecture content
     CLOSED: [2020-07-14 화 00:19]
     - Environment like in Django 1 and Django 3
       - Ensure your nginx is working
     - Follow steps on https://docs.djangoproject.com/en/3.0/intro/tutorial04/

* 2020-07-08
*** Django #4: Tutorial 3
**** DONE Lecture content
     CLOSED: [2020-07-14 화 00:18]
     - Environment like in Django 1 and Django 3
       - Ensure your nginx is working
     - Follow steps on https://docs.djangoproject.com/en/3.0/intro/tutorial03/
* 2020-07-06
*** Django #3: using http and https
**** DONE Lecture content
     CLOSED: [2020-07-14 화 00:17]
     - We want expose our Django app via https to the world
     - We want to allow IPv6 world wide access
     - Steps IPv6
       - Ensure you have IPv6 connectivity
       - Get a VPN from IPv6VPN.ch if you don't have IPv6
       - Ensure that your firewall allows access to ports 80 and 443
         to your machine
       - Coordinate with another participant to test your connection
         - The square brackets are needed in the following examples
         - curl -vv http://[your ipv6 address]
         - curl -vv https://[your ipv6 address]
         - Both examples should return "connection refused"
     - Find out your Domain name
       - We will install an letsencrypt certificate
       - Certificates need a name
       - The website https://has-a.name provides you with a name
       - Find out your name
       - Have somebody else ping your name
     - Steps webserver
       - Install nginx
       - Have somebody else run curl -v http://<your name>.has-a.name
       - Install certbot
       - Use certbot to request a certificate for your name
       - Use the nginx plugin of certbot
       - Have somebody else run curl -v https://<your name>.has-a.name
         (with httpS!)
     - Proxy configuration
       - We want nginx to forward the HTTPS requests to django
       - We run django on the IPv6 localhost
         - python manage.py runserver '[::1]:8000'
         - Note: this is different from last session!
       - We configure nginx to proxy to django
         - Locate the configuration file for the https server (usually
           somewhere below /etc/nginx)
         - Add a proxy configuration to it
         - The proxy block looks similar to this:
           location / {
             proxy_pass       http://localhost:8000;
             proxy_set_header Host      $host;
             proxy_set_header X-Real-IP $remote_addr;
           }
       - Test with the other participants to reach you!
     - Add your nginx configuration
* 2020-07-04
*** Django #2: Tutorial 2
**** DONE Lecture content
     CLOSED: [2020-07-04 토 01:03]
     - Tutorial 2 of Django
     - Environment like in Django 1
     - https://docs.djangoproject.com/en/3.0/intro/tutorial02/
     - If you have IPv6, allow others to acces your Django server
       with:
       - python manage.py runserver '[::]:8000'
* 2020-06-28
*** Django #1: Introduction
**** Objective
     - We will build a IPv6 ULA registry with Django in the
       next lectures
**** DONE Lecture content
     CLOSED: [2020-07-04 토 01:03]
     - Create a new directory in your learning cirle repository named "django"
     - Write down the answers to the following questions in django/django.org
     - Research and answer the following questions: (1/2 of the time)
       - What is IPv6 ULA?
       - Which registries did exist historically?
       - How should an IPv6 ULA registry work?
     - Get started with Django
       - Create a new python virtual env using `python3 -m venv`
         - Create the venv in django/venv
       - Create a file .gitignore in django/
         - Add 'venv/' (without the quotes to that file
         - Use magit to verify that the venv is being ignored
         - Add and commit the .gitignore file
       - Inside this virtual env, install django using `pip`
       - Go to https://www.djangoproject.com/
       - Finish tutorial 1: https://docs.djangoproject.com/en/3.0/intro/tutorial01/
       - Commit the django code to your repository
       - Exclude '*.pyc' in the .gitignore
       - Also exclude the sqlite database
* 2020-06-17
*** Python #11:
**** DONE Lecture content
     CLOSED: [2020-06-17 수 22:24]
     - Same structure as "Python #2"
     - Exercise 44
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-06-15
*** DONE Python #10:
    CLOSED: [2020-06-15 월 23:55]
**** Lecture content
     - Same structure as "Python #2"
     - Exercise 43
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-06-12
*** Python #9:
**** DONE Lecture content
     CLOSED: [2020-06-12 금 22:43]
     - Same structure as "Python #2"
     - Exercise 42
     - Review all previous exercises, ensure you understand them
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-06-10
*** Python #8:
**** DONE Lecture content
     CLOSED: [2020-06-11 목 00:00]
     - Same structure as "Python #2"
     - Exercises 40-41
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-06-08
*** Python #7:
**** DONE Lecture content
     CLOSED: [2020-06-08 월 22:49]
     - Same structure as "Python #2"
     - Exercises 37-39
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-06-01
*** Python applying learnings from 1..6
**** DONE Lecture notes
     CLOSED: [2020-06-02 화 11:21]
     - Previous topics covered:
       - Printing
       - Formatting
       - Variables
       - Escape Sequences
       - Inputting text
       - Reading arguments / using argv
       - Reading files
       - Defining methods
       - Boolean logic
       - Branching using if/else/elif
       - Loops: for/while
     - Today we write a calculator that saves results in a file in python
       - How it works in general
         You read the input until you read a line that only contains a
         "q". Every input line consists of numbers separated by a
         space. For instance "4 5 9". You will need to .split() the
         input.
     - Steps
       - Create a python script named "calc.py"
       - It takes 1 command line argument (argv), which is the filename
         - We will store the calculations *and* results in this file
       - Create a method named "input_and_calculate_one_line"
         - It does not have any arguments
         - It reads one line via *input*
         - It splits the input (let's say "4 5 9" => [ "4", "5", "9") ])
         - It calculates the result (f.i. 4+5+9 = 18) and stores it in
           a variable (use *sum* over the *list*)
         - It returns a string of the format "4 + 5 + 9 = 18"
         - If the line only contains a "q" it return "" (an empty string)
       - Create a method named "editor" that takes a filename as an argument
         - It opens the file for writing
         - It uses input_and_calculate_one_line in a while loop
         - while the return result is not "", we append the string to
           the file
         - When the return result is "", the function exits
* 2020-05-29
*** Python #6:
**** DONE Lecture content
     CLOSED: [2020-05-29 금 23:48]
     - Same structure as "Python #2"
     - Exercises 32-36
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-05-27
*** Python #5:
**** DONE Lecture content
     CLOSED: [2020-05-27 수 22:30]
     - Same structure as "Python #2"
     - Exercises 27-31
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-05-25
*** Python #4:
**** DONE Lecture content
     CLOSED: [2020-05-27 수 22:41]
     - Same structure as "Python #2"
     - Exercises 23-26
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-05-22
**** DONE Lecture content
     CLOSED: [2020-05-23 토 00:21]
     - Same structure as "Python #2"
     - Exercises 15-22
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-05-20
*** Python #2:
**** DONE Lecture content
     CLOSED: [2020-05-20 수 22:47]
     - Read thoroughly & do exercises 8 to 14
       - Focus on understanding
       - You don't have to type everything
       - But you should ensure you understand everything
     - Commit all source code to ~/ungleich-learning-circle/USERNAME/python-the-hard-way
     - Write down notes / what you learned in the *python.org* file
     - Notify your fellow students when you solved something
       - "I just solved exercise 4!"
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-05-15
*** Python #1:
**** Lecture notes
     - Ensure that you have python3 (at least 3.6) installed
     - Use emacs for editing source files
     - Commit all source code to ~/ungleich-learning-circle/USERNAME/python-the-hard-way
**** DONE Lecture content
     CLOSED: [2020-05-19 화 23:47]
     - Read thoroughly & do exercise 0 to 7
     - Commit your source code in git
     - Commit every time you have a task done
       - Make a new commit in git each time you finish (part of) a task
     - Do all exercises
     - Notify your fellow students when you solved something
     - Ask help to other students when you are stuck (but try to solve
       on your own before)
**** Lecture material
     - Available on https://cloud.ungleich.ch/s/435FyfrQyEq6oF3
* 2020-05-15
*** cdist #6: Glueing it together
**** Lecture content
***** Objective
      - Apply learnings from the previous cdist sessions
***** DONE Steps 1: *__all_in_one* (1.25h)
      CLOSED: [2020-05-15 금 23:16]
      - Create a new type named *__all_in_one*
        - Decide yourself whether it is a singleton or not
        - Reason why in your cdist.org file
      - It should work on alpine, debian and fedora
      - It accepts the following parameters:
        - *--with-x* (boolean)
        - *--extra-packages* (optional multiple)
      - On Alpine, it should install netcat-openbsd and tshark
      - On Debian, it should install netcat tshark
      - On Fedora, it should install nmap-ncat wireshark-cli
      - On all operating systems install socat sipcalc sudo
      - If the detected operating system is neither
        Alpine/Debian/Fedora, output an error message and abort the
        manifest with exit code 1
      - Additionally install all packages specified by the *--extra-packages* parameter
***** TODO Steps 2: *__firewall* (1.25h)
      - Create a new type *__my_firewall*
      - Add a *type explorer* to find out whether nft is present on
        the target system
      - Add a required parameter named *file*
      - If the type explorer does not detect nft on the target system,
        abort with an error message
      - Deploy the specified file to */etc/my-nftables*
      - Add a *type explorer* that reads the current nft rules
      - If the rules are different on the target host, apply the new
        ruleset by generating code in *gencode-remote*
      - If the filename specified by the *file* parameter is *-* (the
        minus sign), then the type should read from *stdin*
***** TODO Step 3: manifest (0.5h)
      - Create a new manifest in the folder that contains the initial manifest
      - Name the new manifest *firewall*
      - Source the *firewall* manifest in the *initial* manifest
      - In the *firewall* manifest, match on *localhost*
        - Install nftables
        - Use the *__firewall* type
        - Use correct *require* parameter to ensure that nftables is
          installed before the *__firewall* type is run
* 2020-05-13
*** cdist #5: Generating Code & Exploring
**** Lecture content
***** Objective
      - Understand how to *generate code* and when to use it
      - Exploring explorers
***** DONE Code generation steps
      CLOSED: [2020-05-14 목 00:54]
      - Modify the previously created type *__my_nginx_site*
      - Read about cdist messaging
      - If there was a change in the nginx configuration file, reload nginx
***** DONE Explorer steps
      CLOSED: [2020-05-14 목 00:54]
      - Modify the *__my_nginx_site* type to use the *os explorer*
      - Adjust your type to work on Alpine Linux and Debian (or two
        other Linux distributions of your choice)
      - Set the nginx configuration directory accordingly
***** DONE Documentation
      CLOSED: [2020-05-14 목 00:54]
      - Explain the following in your cdist.org file
      - What is the difference between gencode-remote and the remote code?
      - What is the difference between gencode-local and gencode-remote?
      - Locate a type that comes with upstream cdist that uses
        gencode-local - which one is it? Why does it need gencode-local?
* 2020-05-11
*** cdist #4: Requirements
**** Lecture content
***** Objective
      - Understand how requirements work
***** DONE Create a new type *__my_nginx*
      CLOSED: [2020-05-12 화 02:22]
      - Make it a *singleton*
      - Make it install nginx
      - Configure a host with it
      - Usually nginx is configured includes some files
      - On the target host find out which directory nginx includes
      - We name this directory *nginx_config_dir*
***** DONE Create a new type *__my_nginx_site*
      CLOSED: [2020-05-12 화 02:22]
      - Assume the *object_id* is a *domain*
      - In the __my_nginx_site create a file inside the *nginx_config_dir*
      - The filename is *${domain}.conf*
      - When using *__file*, it should *require* the *nginx package*
        - Read about cdist dependencies
      - The file should be a valid nginx configuration
      - The *server name* should be set to the specified domain
      - The *root* directive should point to /var/www/html/DOMAIN
        - (replace DOMAIN with the actual domain)
***** DONE Use both types in the initial manifest to configure the target host
      CLOSED: [2020-05-15 금 21:07]
      - Create at least two domains
***** DONE Configure the target host
      CLOSED: [2020-05-15 금 21:08]
      - Verify that the configuration files are properly created
***** DONE Delete the nginx package manually on the target host
      CLOSED: [2020-05-15 금 21:08]
***** DONE Comment out *__my_nginx* from the initial manifest, keep the *__my_nginx_site*
      CLOSED: [2020-05-15 금 21:08]
      - Explain the error that you get (in your cdist.org file)
* 2020-05-08
*** cdist #3: type parameters
**** Lecture content
***** DONE Create a new type named *__colourful_file*
      CLOSED: [2020-05-15 금 20:29]
      - The objective is to create a type that creates colourful file
      - The content of the file should be "colour=...", where "..." is a colour specified by a parameter
      - Add an *optional parameter* named *colour*
      - Use the **__file** type inside your type to create a file
      - Use the *$__object_id* variable inside your type
***** DONE Extend your type to be more colourful
      CLOSED: [2020-05-15 금 20:29]
      - Modify the *optional parameter* to be able to be specified *multiple times*
      - For each time it is specified, add a line "colour=..." to the file
***** DONE Create a new type *__my_dotfiles*
      CLOSED: [2020-05-15 금 21:07]
      - Objective is to manage the dotfiles in your home directory
      - Make it a *singleton* type
      - Create a sub directory *files* in the type
      - Add your .emacs config to the files folder
      - Add a *for* loop to your type to deploy .[A-z]* to your home directory
      - Add a .bashrc or .zshrc to the files folder (depending on your shell)
      - In the initial manifest, add __my_dotfiles when the target host is localhost
***** DONE As usual commit all changes to your ungleich-learning-circle repo
      CLOSED: [2020-05-15 금 21:07]
* 2020-05-06
*** cdist #2: Your first cdist type
**** Lecture content
***** Objective
****** Begin to understand how cdist types function
***** Steps
****** Create a new type named `__my_computer`
        - Mark the type as a singleton type
        - Create a `manifest` file in it
        - Use this type to install the following packages: zsh, mosh, emacs, nmap, sipcalc
        - Edit the *initial manifest* and use **__my_computer** for **localhost**
        - Match using the $__target_host variable
****** Modify your type to use a *for loop* to install the packages
****** Deploy / manage your ~/.emacs file in this type
       - Ensure that permissions and ownership are correct
****** Use different *verbosity* levels when configuring
****** Ensure that all your changes are committed and pushed in your ungleich-learning-circle repository
       - Use magit inside emacs for that
***** Documentation steps to be done in cdist.org
       - Create a new org document named `cdist.org` in the same folder as the learning.org file
       - Explain the difference between a singleton and non-singleton type
       - Explain the difference between the different verbosity levels
       - Document (copy&paste) some of the cdist runs in a "log" section```
* 2020-05-04
*** cdist #1: Introduction
**** Lecture content
***** Objective
      - Begin to use cdist
***** Steps
      - Checkout cdist quickstart https://www.cdi.st/manual/latest/cdist-quickstart.html
      - Install cdist locally
      - Create a new cdist configuration directory in ~/ungleich-learning-circle/USERNAME/dot-cdist
      - Create an empty initial manifest ("use touch")
      - Commit that status
      - Ensure that you can login as root to localhost via ssh without a password
      - Configure cdist to configures the motd of your localhost
        - Ensure you have a case block matching on $__target_host
        - Use the -c parameter to cdist to specify the configuration directory
        - Use the -vv parameter to get more verbose output
        - Search for / understand what MOTD stands for
      - Configure cdist to create the file /etc/cdist-configured
      - Configure cdist to setup the timezone on your local computer
      - Configure cdist to ensure emacs is installed
      - Ensure that in the end all changes are committed in your repository
* 2020-05-01
*** Organisation #5: Emacs refresher
**** Lecture content
***** Objective: get confident with emacs commands
***** Find out and document how to do the following steps
      - Search for something forward C-s
      - How to continue searching C-s C-s
      - Search for something backward C-r
      - Search for regular expressions instead of string (forward, backward) C-M-s C-M-r
      - Go to the beginning of the line C-a
      - Go to the end of the line C-e
      - Delete a word in front (to the right of the cursor) M-d
      - Delete a word in back (to the left of the cursor) M-BackSpace
      - List all "occurences" of a word in a file M-s o
        - You can copy above instructions into an emacs buffer
        - And test it by showing all occurences of the word "Search"
      - Search (GREP) for a word in all files in a directory RECURSIVELY M-x rgrep
      - Save the CURRENT buffer C-x C-s
      - Save ALL open files C-x-s
      - Split the window/buffer vertically C-x 2
      - Split the window/buffer horizontally C-x 3
      - Switch between the different windows C-x o
      - Close all buffers besides the active one C-x 1
        - Don't kill it!
      - Close only the active buffer C-x 0
        -* Don't kill it!
      - Kill the active buffer C-x k
      - Describe/Explain the difference between closing and killing
        - closing is that emac do not display the buffer. and the contents on the buffer are kept on behined screen.
        - killing is that emac delete the buffer. and if contents are not stored, it is losted
      - Switch between buffers that are not shown C-x b
        - Document two very similar, but slightly different ways
          - C-x b is that the selected buffer is displayed on the focused window
          - C-x C-b is that all buffers is dispalayed on the new window
          - C-x 4 b is that the selected buffer is displayed on the new window
***** Outcome
      - Document all above commands in your learning org sheet
      - Share your documentation at the end of the session (not before)
* 2020-04-29
*** Organisation #4: Organising yourself
**** Lecture content
***** Objective: have a todo list based on org mode
***** Steps
      - Configure the "org-directory" to be ~/ungleich-learning-circle/USERNAME/
        - This is important as it will be used by the todo function later
      - Extend your function from the organisation #1 session
        - Instead of opening a fixed file, we include two variable parts:
          - The hostname of the machine
          - The year
        - Pressing F3 should open ~/ungleich-learning-circle/USERNAME/learning-$(hostname)-$(year).org
          - we call this "your personal agenda"
      - Configure mu4e to create a org-mode tasks from an email
        - Store these tasks in ~/ungleich-learning-circle/USERNAME/todo.org
      -  Configure emacs to open the "org-agenda" with "C-c a"
      - List all TODO entries
      - List the agenda of the day
      - List the agenda of the week
      - Bind F8 to open the "org-todo-list"
      - Create some sample tasks in it
***** From now on, maintaining tasks should be
      - Pressing F3 to open your personal "logfile"
      - Adding a TODO item
      - Pressing F8 to see the tasks with priorities
***** Bonus tasks
      - Configure mu4e to store org-mode tasks in .../todo-$(hostname)-$(year).org
* 2020-04-27
*** Organisation #3: Managing your emails
**** Lecture content
***** Objective
      - Be able to manage all your mails in mu4e
***** Description
      - All email is synchronised using isync/mbsync
      - Email is indexed with mu (xapian backend)
      - Email is viewed in mu4e
      - All new emails arrive in the inbox
***** Steps
      - Install mu4e
      - Start mu4e in emacs
      - Configure mbsync for your ungleich mail account
        - Synchronise all mails into ~/Maildir/ungleich
        - This structure leaves room for other mail accounts, like ~/Maildir/gmail
      - Verify that mbsync synchronises the mail
      - Index mails using `mu` on the command line (only first time)
      - Configure mu4e to get email with mbsync -a
      - Configure mu4e to "archive" emails into ~/Maildir/ungleich/YEAR/
        - This gives you a good performance / organisation for the next decades
      - Configure mu4e/emacs for sending emails
      - Send other participants an email via mu4e
      - Verify that it arrives
      - "Archive" it afterwards
* 2020-04-24
*** Organisation #2: Creating, managing and sharing with "magit"
**** Lecture content
***** Install "magit" for emacs
***** Bind C-x g to open magit-status in ~/.emacs
***** Create a new directory ~/ungleich-learning-circle/ (with emacs)
      - Use C-h b in dired mode to find out how to
***** Create a sub directory ~/ungleich-learning-circle/YOURNAME/ (with emacs)
***** Move your previously created learning.org file into ~/ungleich-learning-circle/YOURNAME/ (with emacs)
***** Initialise it with git (with magit)
***** Create the repo "ungleich-learning-circle" on code.ungleich.ch under your username
***** Add your remote on code.ungleich.ch to your local git repo with magit
***** Push your repo
***** Add a new remote of a another participant 
***** Move your ~/learning.org to ~/notes
***** Commit that file with magit
***** Push the repo with magit
***** Merging the remote repo with the command line
***** End result: everyone has everything of everyone else
* 2020-04-23
*** Organisation #1: org-mode introduction
**** Lecture content
***** Install emacs
***** Install org-mode
***** Create a function that opens ~/learning.org in your ~/.emacs
***** Bind that function to "f3" (configure it in .emacs)
***** Create a new item named "2020-04-10"
      - Create a sub item "ungleich learning circle"
