From 2e05599294192c5c69b742e32690b9575f80e25c Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Tue, 10 Oct 2023 12:36:58 +0200 Subject: [PATCH 1/7] Enable wake-on-lan. --- roles/lmn_kde/tasks/main.yml | 6 ++++++ roles/lmn_network/tasks/main.yml | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/roles/lmn_kde/tasks/main.yml b/roles/lmn_kde/tasks/main.yml index 6fc7ba8..ea70a3a 100644 --- a/roles/lmn_kde/tasks/main.yml +++ b/roles/lmn_kde/tasks/main.yml @@ -91,6 +91,12 @@ RememberLastUser=false RememberLastSession=false +- name: Enable wake-on-lan for all ethernet connections + ansible.builtin.copy: + dest: /etc/NetworkManager/conf.d/wake-on-lan.conf + content: | + [connection] + ethernet.wake-on-lan=64 - name: Create directory to avoid suspend ansible.builtin.file: diff --git a/roles/lmn_network/tasks/main.yml b/roles/lmn_network/tasks/main.yml index 3a51738..853f4b6 100644 --- a/roles/lmn_network/tasks/main.yml +++ b/roles/lmn_network/tasks/main.yml @@ -8,13 +8,13 @@ ftp_proxy="{{ proxy }}" no_proxy="{{ no_proxy }}" -- name: set aptcache +- name: Set aptcache ansible.builtin.copy: dest: /etc/apt/apt.conf content: > {{ apt_conf }} -- name: set ntp Server +- name: Set NTP server ansible.builtin.lineinfile: path: /etc/systemd/timesyncd.conf insertafter: '^#NTP=' From c1a6b35b9c64f4b23865da1c1cea2482c3afa006 Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Tue, 10 Oct 2023 12:38:21 +0200 Subject: [PATCH 2/7] Support for veracrypt. --- roles/lmn_fvs/tasks/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/lmn_fvs/tasks/main.yml b/roles/lmn_fvs/tasks/main.yml index 0f708db..787bde4 100644 --- a/roles/lmn_fvs/tasks/main.yml +++ b/roles/lmn_fvs/tasks/main.yml @@ -50,6 +50,8 @@ - ttf-mscorefonts-installer - unison-gtk - wireshark + - zulucrypt-gui +# - python-is-python3 autoremove: true state: latest environment: From 1bdb0e5b3887a247349dce90f7b22758c39db780 Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Wed, 11 Oct 2023 18:23:08 +0200 Subject: [PATCH 3/7] When shutdown is chosen from within KDE, the system hangs. --- lmn-desktop.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lmn-desktop.yml b/lmn-desktop.yml index 2f3ee76..d96c72c 100644 --- a/lmn-desktop.yml +++ b/lmn-desktop.yml @@ -133,6 +133,13 @@ APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; +## bookworm fixes/hacks: + - name: Work around sddm hang on shutdown + ansible.builtin.lineinfile: + path: /etc/systemd/system.conf + line: DefaultTimeoutStopSec=5s + insertafter: '^#DefaultTimeoutStopSec=.*' + ## bullseye fixes: - name: Add bookworm firmware repository if needed apt_repository: From 445c31b7b7990b3b419d4f95640ebf4796626f49 Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Wed, 11 Oct 2023 21:05:00 +0200 Subject: [PATCH 4/7] Provide libdvdcss needed for playing video DVDs. --- lmn-desktop.yml | 3 +++ roles/lmn_fvs/tasks/main.yml | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/lmn-desktop.yml b/lmn-desktop.yml index d96c72c..d80e4c0 100644 --- a/lmn-desktop.yml +++ b/lmn-desktop.yml @@ -40,6 +40,9 @@ ## Local mirror for mscorefonts. Remove or leave empty to use no mirror: mirror_msfonts: http://livebox.pn.steinbeis.schule/mscorefonts/ + ## Local mirror for libdvdcss. Remove or leave empty to use no mirror: + mirror_dvdcss: http://livebox.pn.steinbeis.schule/libdvdcss/ + rsyncsecret: Muster! keys2deploy: - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKOY0hChWaCDtuiuQcM0v4/u1499esjTtnMjl4uYlnS0 andi@netboot' diff --git a/roles/lmn_fvs/tasks/main.yml b/roles/lmn_fvs/tasks/main.yml index 787bde4..fdf4404 100644 --- a/roles/lmn_fvs/tasks/main.yml +++ b/roles/lmn_fvs/tasks/main.yml @@ -171,6 +171,19 @@ # LockOnResume=false # +- name: Download libdvdcss from mirror + ansible.builtin.get_url: + url: "{{ mirror_dvdcss }}/libdvdcss.so.2.2.0" + dest: /usr/lib/x86_64-linux-gnu/libdvdcss.so.2.2.0 + when: mirror_dvdcss is defined and mirror_dvdcss | length > 0 + +- name: Link library so name + ansible.builtin.file: + src: libdvdcss.so.2.2.0 + dest: /usr/lib/x86_64-linux-gnu/libdvdcss.so.2 + state: link + when: mirror_dvdcss is defined and mirror_dvdcss | length > 0 + - name: Patch sddm login screen to show hostname blockinfile: path: /usr/share/sddm/themes/debian-breeze/Main.qml From df7ea045766e2c83b59f1e222e68c6c6c9e12818 Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Wed, 11 Oct 2023 21:34:20 +0200 Subject: [PATCH 5/7] Install php-cli on request. --- roles/lmn_fvs/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/lmn_fvs/tasks/main.yml b/roles/lmn_fvs/tasks/main.yml index fdf4404..a41e5cc 100644 --- a/roles/lmn_fvs/tasks/main.yml +++ b/roles/lmn_fvs/tasks/main.yml @@ -41,6 +41,7 @@ - net-tools - netcat-openbsd - nmap + - php-cli - planner - pulseview - sigrok @@ -51,7 +52,6 @@ - unison-gtk - wireshark - zulucrypt-gui -# - python-is-python3 autoremove: true state: latest environment: From 0b413b7835491609ecab5fa4f0bf2abff0b69d44 Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Thu, 12 Oct 2023 10:00:26 +0200 Subject: [PATCH 6/7] Download fails during installation. --- inventory/inventory.yml | 3 ++- roles/lmn_fvs/tasks/main.yml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/inventory/inventory.yml b/inventory/inventory.yml index 1ec28a2..9560e51 100644 --- a/inventory/inventory.yml +++ b/inventory/inventory.yml @@ -96,7 +96,8 @@ L300: hosts: 10.190.52.61: 10.190.52.[91:92]: -# 10.190.52.[1:10]: + 10.190.52.121: + 10.190.52.151: L400: hosts: # 10.190.53.[1:10]: diff --git a/roles/lmn_fvs/tasks/main.yml b/roles/lmn_fvs/tasks/main.yml index a41e5cc..0c082c5 100644 --- a/roles/lmn_fvs/tasks/main.yml +++ b/roles/lmn_fvs/tasks/main.yml @@ -175,6 +175,7 @@ ansible.builtin.get_url: url: "{{ mirror_dvdcss }}/libdvdcss.so.2.2.0" dest: /usr/lib/x86_64-linux-gnu/libdvdcss.so.2.2.0 + use_proxy: False when: mirror_dvdcss is defined and mirror_dvdcss | length > 0 - name: Link library so name From 79ec9e57f2024ef495e062d3e568c5bda5b6c2bf Mon Sep 17 00:00:00 2001 From: "Andreas B. Mundt" Date: Thu, 12 Oct 2023 20:00:19 +0200 Subject: [PATCH 7/7] Use vault for site-specific variables. --- inventory/inventory.yml | 2 +- lmn-desktop.yml | 78 ++++++++++++++---------------------- lmn-laptop.yml | 83 +++++++++++++++++++++++++++++--------- lmn-vault | 88 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 69 deletions(-) create mode 100644 lmn-vault diff --git a/inventory/inventory.yml b/inventory/inventory.yml index 9560e51..9196bd9 100644 --- a/inventory/inventory.yml +++ b/inventory/inventory.yml @@ -94,7 +94,7 @@ L200: # 10.190.51.[1:10]: L300: hosts: - 10.190.52.61: + 10.190.52.[61:62]: 10.190.52.[91:92]: 10.190.52.121: 10.190.52.151: diff --git a/lmn-desktop.yml b/lmn-desktop.yml index d80e4c0..ada2686 100644 --- a/lmn-desktop.yml +++ b/lmn-desktop.yml @@ -1,4 +1,21 @@ ## This playbook deploys a KDE desktop machine for LinuxMuster. +# +# Use the following in the installer's preseed file: +# +# d-i preseed/late_command string \ +# mkdir -p /target/home/ansible/.ssh && \ +# echo "ssh-ed25519 A...YOUR.KEY...Z" >> /target/home/ansible/.ssh/authorized_keys ; \ +# in-target chown -R ansible:ansible /home/ansible/.ssh/ ; \ +# in-target chmod -R og= /home/ansible/.ssh/ ; \ +# if [ -n "$playbook" ] ; then \ +# mkdir -v /target/dev/shm ; \ +# in-target mount -v -t tmpfs tmpfs /dev/shm ; \ +# echo "$vaultpw" > /target/dev/shm/vaultpw ; \ +# in-target ansible-pull --verbose --purge --extra-vars="run_in_installer=true" \ +# --vault-password-file /dev/shm/vaultpw \ +# -i localhost, --url=git://ansible.example.org/.git -C YOUR_BRANCH $playbook ; \ +# fi +# --- - name: apply configuration to the machines hosts: all @@ -26,35 +43,29 @@ value: True vtype: boolean + vars_files: lmn-vault vars: domain: "{{ ansible_domain }}" - kerberize_uris: steinbeis.schule - apt_conf: Acquire::http::Proxy "http://aptcache.pn.steinbeis.schule:3142/"; - ntp_serv: server.pn.steinbeis.schule - proxy: http://firewall.pn.steinbeis.schule:3128 - no_proxy: firewall.pn.steinbeis.schule,server.pn.steinbeis.schule,idam.steinbeis.schule,dw.steinbeis.schule,.pn.steinbeis.schule,.steinbeis.schule + kerberize_uris: "{{ vault_kerberize_uris }}" ## example.org + apt_conf: "{{ vault_apt_conf }}" ## Acquire::http::Proxy "http://aptcache.example.org:3142/"; + ntp_serv: "{{ vault_ntp_serv }}" ## ntp.example.org + proxy: "{{ vault_proxy }}" ## http://firewall.example.org:3128 + no_proxy: "{{ vault_no_proxy }}" ## firewall.example.org,server.example.org,idam.example.org,dw.example.org ## PAM mount nextcloud, remove or leave empty to skip: - web_dav: https://nc.steinbeis.schule/remote.php/dav/files/%(USER) + web_dav: "{{ vault_web_dav }}" ## https://nc.example.org/remote.php/dav/files/%(USER) ## Local mirror for mscorefonts. Remove or leave empty to use no mirror: - mirror_msfonts: http://livebox.pn.steinbeis.schule/mscorefonts/ + mirror_msfonts: "{{ vault_mirror_msfonts }}" ## http://livebox.example.org/mscorefonts/ ## Local mirror for libdvdcss. Remove or leave empty to use no mirror: - mirror_dvdcss: http://livebox.pn.steinbeis.schule/libdvdcss/ + mirror_dvdcss: "{{ vault_mirror_dvdcss }}" ## http://livebox.example.org/libdvdcss/ - rsyncsecret: Muster! - keys2deploy: - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKOY0hChWaCDtuiuQcM0v4/u1499esjTtnMjl4uYlnS0 andi@netboot' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAN5ylqP936MPjGNxzrzV5jMwIfMhKJdOGuVh3xGQKTM andi@yogi' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHxgeu7Rpb/1++531+MopqP9haUkyh1XXpv5kmbgSjx6' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBbdOT+WSDmsBcaVFfzPRcmvOfd3CqO/FBOH44UVm7c7 raphael@uranus' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGICjy88HnMg5oaz4BJ20hgzqFWSem+HHD2PQ+As42pA raphael@pluto' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKm9lu9dDo5TG99QWTkl2G5G+ZbYikLlRNOXfs/bRTHy sascha@america' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMR4TP7jE+wS7zcH0iUBmlxCbvy9saYeEjonX/0yYfEJ daniel@NB-20-DW' + rsyncsecret: "{{ vault_rsyncsecret }}" + keys2deploy: "{{ vault_keys2deploy }}" ## ['ssh-ed25519 AAAAC…uYlnS0', 'ssh-ed25519 AAAA…KTM'] ## Use grub-mkpasswd-pbkdf2 to calculate the password hash: - grub_pwd: 'grub.pbkdf2.sha512.10000.FB60266F69FB181327AFB76193192454FC64151559EFF4D6B8FB7C7904A2A9C4778EDD515B46F770DB6A009F36903C193917BBBC571C5B6AAB2A69208BE01A6E.7B82114A0239C0EC55A50E95C48FA74A8910DEE4088447786DAB35770B9C2CF2D1550CF3B7452155EB55D5F84E5D357BF12B8D299CF9B01BF5D71D516CF826DB' + grub_pwd: "{{ vault_grub_pwd }}" nfs4: false extra_pkgs: - vim @@ -78,16 +89,6 @@ - lmn_security tasks: - - name: Add local user 'virti' in the 'libvirt' group - ansible.builtin.user: - name: virti - password: $y$j9T$DuSvAO63v5LvoJmJ1rB0B0$D4tovIz79AdLHs5I6tYa7rxr3SWknQeUFvGaaKvUpo3 - comment: Libvirt VM User,,, - shell: /bin/bash - groups: libvirt - append: yes - when: false - ## Temporary fixes and quirks: - name: Fix 8086:4909 external graphics card replace: @@ -142,24 +143,3 @@ path: /etc/systemd/system.conf line: DefaultTimeoutStopSec=5s insertafter: '^#DefaultTimeoutStopSec=.*' - -## bullseye fixes: - - name: Add bookworm firmware repository if needed - apt_repository: - repo: deb http://deb.debian.org/debian/ bookworm non-free-firmware - state: present - update_cache: true - when: > - ansible_board_vendor == "LENOVO" and - ansible_board_name == "32CB" and - ansible_distribution_release == "bullseye" - - - name: upgrade non-free-firmware packages - apt: - upgrade: true - autoremove: true - autoclean: true - when: > - ansible_board_vendor == "LENOVO" and - ansible_board_name == "32CB" and - ansible_distribution_release == "bullseye" diff --git a/lmn-laptop.yml b/lmn-laptop.yml index 0974cab..88010f9 100644 --- a/lmn-laptop.yml +++ b/lmn-laptop.yml @@ -11,7 +11,7 @@ register: adpw no_log: true when: "ansible_cmdline.adpw is not defined" - - name: preseed apparmor + - name: Preseed apparmor debconf: name: apparmor question: apparmor/homedirs @@ -26,33 +26,30 @@ value: True vtype: boolean + vars_files: lmn-vault vars: domain: "{{ ansible_domain }}" - kerberize_uris: steinbeis.schule - apt_conf: Acquire::http::Proxy "http://aptcache.pn.steinbeis.schule:3142/"; - ntp_serv: server.pn.steinbeis.schule - proxy: http://firewall.pn.steinbeis.schule:3128 - no_proxy: firewall.pn.steinbeis.schule,server.pn.steinbeis.schule,idam.steinbeis.schule,dw.steinbeis.schule,.pn.steinbeis.schule,.steinbeis.schule + kerberize_uris: "{{ vault_kerberize_uris }}" ## example.org + apt_conf: "{{ vault_apt_conf }}" ## Acquire::http::Proxy "http://aptcache.example.org:3142/"; + ntp_serv: "{{ vault_ntp_serv }}" ## ntp.example.org + proxy: "{{ vault_proxy }}" ## http://firewall.example.org:3128 + no_proxy: "{{ vault_no_proxy }}" ## firewall.example.org,server.example.org,idam.example.org,dw.example.org ## PAM mount nextcloud, remove or leave empty to skip: - web_dav: https://nc.steinbeis.schule/remote.php/dav/files/%(USER) + web_dav: "{{ vault_web_dav }}" ## https://nc.example.org/remote.php/dav/files/%(USER) ## Local mirror for mscorefonts. Remove or leave empty to use no mirror: - mirror_msfonts: http://livebox.pn.steinbeis.schule/mscorefonts/ + mirror_msfonts: "{{ vault_mirror_msfonts }}" ## http://livebox.example.org/mscorefonts/ - rsyncsecret: Muster! - wifipasswd: FjgmGBaKEenr25ZF - keys2deploy: - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKOY0hChWaCDtuiuQcM0v4/u1499esjTtnMjl4uYlnS0 andi@netboot' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAN5ylqP936MPjGNxzrzV5jMwIfMhKJdOGuVh3xGQKTM andi@yogi' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHxgeu7Rpb/1++531+MopqP9haUkyh1XXpv5kmbgSjx6' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBbdOT+WSDmsBcaVFfzPRcmvOfd3CqO/FBOH44UVm7c7 raphael@uranus' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGICjy88HnMg5oaz4BJ20hgzqFWSem+HHD2PQ+As42pA raphael@pluto' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKm9lu9dDo5TG99QWTkl2G5G+ZbYikLlRNOXfs/bRTHy sascha@america' - - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMR4TP7jE+wS7zcH0iUBmlxCbvy9saYeEjonX/0yYfEJ daniel@NB-20-DW' + ## Local mirror for libdvdcss. Remove or leave empty to use no mirror: + mirror_dvdcss: "{{ vault_mirror_dvdcss }}" ## http://livebox.example.org/libdvdcss/ + + rsyncsecret: "{{ vault_rsyncsecret }}" + wifipasswd: "{{ vault_wifipasswd }}" + keys2deploy: "{{ vault_keys2deploy }}" ## ['ssh-ed25519 AAAAC…uYlnS0', 'ssh-ed25519 AAAA…KTM'] ## Use grub-mkpasswd-pbkdf2 to calculate the password hash: - grub_pwd: 'grub.pbkdf2.sha512.10000.FB60266F69FB181327AFB76193192454FC64151559EFF4D6B8FB7C7904A2A9C4778EDD515B46F770DB6A009F36903C193917BBBC571C5B6AAB2A69208BE01A6E.7B82114A0239C0EC55A50E95C48FA74A8910DEE4088447786DAB35770B9C2CF2D1550CF3B7452155EB55D5F84E5D357BF12B8D299CF9B01BF5D71D516CF826DB' + grub_pwd: "{{ vault_grub_pwd }}" nfs4: false extra_pkgs: - vim @@ -77,9 +74,57 @@ - lmn_security tasks: +## Temporary fixes and quirks: + - name: Fix 8086:4909 external graphics card + replace: + dest: "/etc/default/grub" + regexp: 'GRUB_CMDLINE_LINUX=""$' + replace: 'GRUB_CMDLINE_LINUX="i915.force_probe=4909"' + notify: Run update-grub + when: ansible_board_vendor == "LENOVO" and ansible_board_name == "32CB" + + - name: Fix sound on 312A + replace: + dest: "/etc/default/grub" + regexp: 'GRUB_CMDLINE_LINUX="snd-intel-dspcfg.dsp_driver=1"$' + replace: 'GRUB_CMDLINE_LINUX=""' + notify: Run update-grub + when: ansible_board_vendor == "LENOVO" and ansible_board_name == "312A" + + - name: Fix sound on 312A and 312D + apt: + name: firmware-sof-signed + state: latest + when: > + ansible_board_vendor == "LENOVO" and + (ansible_board_name == "312D" or ansible_board_name == "312A") + +## Clean up stuff from obsolete/faulty tasks: + - name: Remove virtiofs service + file: + path: /etc/systemd/system/virtiofs@.service + state: absent + + - name: Fix mount point permissions and owner + file: + path: "{{ item }}" + mode: '0755' + owner: root + group: root + loop: + - /srv/samba + - /srv/samba/schools + - name: Fix unattended-upgrades ansible.builtin.copy: dest: /etc/apt/apt.conf.d/20auto-upgrades content: | APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; + +## bookworm fixes/hacks: + - name: Work around sddm hang on shutdown + ansible.builtin.lineinfile: + path: /etc/systemd/system.conf + line: DefaultTimeoutStopSec=5s + insertafter: '^#DefaultTimeoutStopSec=.*' diff --git a/lmn-vault b/lmn-vault new file mode 100644 index 0000000..0cac093 --- /dev/null +++ b/lmn-vault @@ -0,0 +1,88 @@ +$ANSIBLE_VAULT;1.1;AES256 +32636664616238393662376463373731633938323336623065323763613332363661353833643236 +3063383038383733393431626336373261666333373438360a346330663233333338643765366139 +30616635336234653861663938376237613066356130383066653137343363633666326264656434 +3635633262366330640a663839383661343464643938363333393734383737653736326562666564 +36346338623363626261666563336564346533393532666130646534646532613632396561363966 +39613563613131663564653934636131653365633132363536373732303437643938306264376130 +33643262323365363535353036333535663037353938356663346238643836386666663561303264 +64353262633532353236343537373137353135336438366335646532373961343931636433306232 +32383730643962333064653833666537383336366234343730623832336238633537333038353236 +33613164353737323838343465353630626665303836303865663864306332393039613265383630 +31353234626664626133333465386166353635343364363765346138633362333161666438363866 +61323433323363363531396530326365306532656530363335613364373964323665393761313932 +32316330386231623934636661396466613932356531383533653331643431323238646566343734 +32636337613165643164373161376634363361653163636661653762613036336632306138666361 +66656264393033373930613736323037336635633365386662653739316633306138326235363038 +35353366366166323361656161326435363934393239336637393539653532636532366633613233 +66633765636436383165313338663737386539366532323938646562623039613865373132333161 +65366637313966626363383437616631653639656131303932633833643163633831376635373933 +66666430363361656238643833326631373330313333396433666539346431343864336333336465 +34303931653632386238323336383466353266323163383537666538633932383462363637613833 +32346362303464616135333237383061333762623830656162643935616635623166343638663637 +32633962663864626337346566616232333839386438313365323339366435396434323539363938 +36623966343530653366333138633836383538333833643637656536653033386163323064656263 +61633738653461366163643363626364633636616265626232393861376330616234633461323032 +64626537346566303434343534653531306439303563343732616464386333323862323333613365 +31356466326134633961363265336461303462633932653634656334363033323835653765333163 +34353664316361356638333330323364373236313237313962336630613636363038363533653963 +64336463643035613539346466316361393666346136373533343633346464376130393066653965 +64643437376132613731333363396636383939646465346439303737663539646165313164333633 +66333463633865323465313932396265616638383665333239623364356537373930343432373935 +39663635343135613339313937303763613733616662386331336662383865643066373633653863 +34613063636134393965333333663264633863656331363135316238643333393431306236353464 +33633637633665303736663338313061616539376264343536633434313766613466346365656133 +37646434323435313532396633343663616562613937306265643933323461613437633666663230 +64653330616333326665323263663635373936633463663831333932323863323631373033636139 +36366139333230306137356430613761373630666363373062613237383562363630356235626166 +61613239613937346536386465326230623431333233386131383638323563626132663638653136 +38663664636362393339653964663330353663393765333135313965383837333139383832633238 +66616665373336313961393032383432313337336139306530313130306634613939386465353561 +36373462336435303831383764356531643232313434633530303135623134386663643534356238 +39663235326137386130383534363431636139373966336162343536356136616335666561383762 +66666366646261633761666663383566333531323764663664353139386565636661323365636265 +35326637313937346639323136653437313465356532373461333736336437393065363430363262 +32326436373266323835323038326330306635306537316333383864623835636330653837663033 +39613663333232333031643935613066643032353935356238663238383930383035623939383165 +35636538633231383439326432663734613262356339346136616634346461356263336163346433 +31666236316363373132626633386535323635626330613730303134313263646430376433623661 +39656530313135333737656632653731373363653861393562663261666164366161616131376235 +63396435643066633738643965393061376237656232666437366664353037383461393538353239 +65663235343036666538376439313465366333636436646563623961336230346365373764363737 +31616162663438316366323063653334316663646261353230663764383364643864373562323734 +32666262643634663339653332393566356636613662373835313664303035633333396131646165 +61336438333735613963353064393233343565396562383734373365336431643863633938333733 +38653138353763356461326531303733323134323865623361383933396337346533653635353965 +32336236316462656632656161303138613133663861353237396139393930306565313532356365 +39356531626130653430353331373363626264333730346563666234313163613161643162393839 +62356331613863613538376337313837383064373932346138353264663232383565313833346566 +32306366656564393364303830323637323336356665333037623362383363623135646334306438 +65373036656636393536323462363234366538636566373361396530373535333033313233623032 +32373666313462663465373863653433363738646265383338623861366163633638343566393731 +38303162356463656339303337363461386461396639633064323965366464623639366336313537 +39353638616230613264343735333539353366613735363062636233326130666362363363633136 +37313962376233303834313432313565333264343733653835653831343261343437383832373936 +63376461396533613364313236356364393534326339373565316530303437353732653733326232 +37663837333966653238323234316463643339626663643766343735353239633838653336663834 +34373266613336376537363335616134366633373039343934386333343530633962626435366463 +37613562616335363637323361303138653565376466396533336332643365376265643435333435 +32613266356539623230646135333234376135623435666235373266363836653938316266613038 +39653064326661363538343732336437626537366430666639303162653033613631343930643961 +62633432343464333066643830343033643461316166663935383366313665623665346263613037 +64366662626536663765343339343136313863613633316264636531366638303133636539666461 +32383734633837306465323434306338653331356638353731666537623335306532643431353563 +65326339396433666566666631613630663863643935633936313265313866326130383735313031 +32396434643333343962306364643631383164376464316637623739356264343735393838623962 +61323633663633343464663638653761383164363932616630353564666237663530383239353866 +33343236303532366430383331623138633564336538623034643630373138356134393861643039 +39633565343063373533326232383038333330353539346533313433303133366534343033666161 +36306566623361643663333265626561393036633966333331353033393066356138326663356539 +65393066643939373730383437363232366434386636666636643137616465633635393930306335 +62383136376637653861323761646262646162346538393639346139656530303062353764653835 +39363165373633333564353938646331613336316230353331313861363361666265643034633230 +31313033343533386232343039646537336339303434383439353363656632366364656238373835 +35663731313439396435373238363739353935306335646536363961373631373039366331393138 +38663263363731306236323563663965323261626134373532343762363632316339666465323936 +35646462313237656261626138313431303264613032316138613634616133396662356232626565 +36623762656633386463633664363665616564393166313439396138363335666665383838376439 +613237313732306630313738643233333966