Copying setup from other infra repo

This commit is contained in:
2024-01-04 18:45:01 +01:00
parent 42d3138746
commit 4900bc3c0d
21 changed files with 713 additions and 1 deletions

Binary file not shown.

4
ansible.cfg Normal file
View File

@@ -0,0 +1,4 @@
[defaults]
inventory = inventory
remote_user = ansible
# Will use yubikey for ssh authentication

7
decrypt-vault.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
./helpers/get-passwords.sh
ansible-vault decrypt vars/bootstrap.yaml --vault-password-file ./.passwords/vault
ansible-vault decrypt vars/vault.yaml --vault-password-file ./.passwords/vault
./helpers/delete-passwords.sh

7
encrypt-vault.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
./helpers/get-passwords.sh
ansible-vault encrypt vars/bootstrap.yaml --vault-password-file ./.passwords/vault
ansible-vault encrypt vars/vault.yaml --vault-password-file ./.passwords/vault
./helpers/delete-passwords.sh

16
git-hooks/commit-msg Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
# TODO: Clean this up so it iterates over the vars files
if grep -qE "vault_decrypted: true" "./vars/bigboi.yaml";then
echo "The vault isn't encrypted, run './encrypt-vault.sh' before committing."
exit 1
fi
if grep -qE "vault_decrypted: true" "./vars/bootstrap.yaml";then
echo "The vault isn't encrypted, run './encrypt-vault.sh' before committing."
exit 1
fi
if grep -qE "vault_decrypted: true" "./vars/smolboi.yaml";then
echo "The vault isn't encrypted, run './encrypt-vault.sh' before committing."
exit 1
fi

9
helpers/delete-passwords.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
if [[ -d "./.passwords" ]]
then
rm -rf "./.passwords"
echo "Deleted passwords"
else
echo "There were no passwords to delete"
fi

2
helpers/generate-password.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
mkpasswd --method=sha-512

14
helpers/get-passwords.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
if ! [[ -d "./.passwords" ]]
then
mkdir "./.passwords"
echo "Created passwords directory"
fi
pass wholteza/encryption-keys/ansible/git.nmlk.se/vault > ./.passwords/vault
echo "Fetched vault password"
pass wholteza/network/linode/linone/ansible > ./.passwords/become
echo "Fetched ansible user password"
pass wholteza/network/linode/linone/wholteza > ./.passwords/bootstrap_become
echo "Fetched bootstrap user password"

7
install-requirements.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
sudo apt update \
&& sudo apt install ansible \
&& ansible-galaxy collection install community.general \
&& ansible-galaxy collection install ansible.posix
cp ./git-hooks/commit-msg ./.git/hooks/commit-msg

2
inventory Normal file
View File

@@ -0,0 +1,2 @@
[prod]
git.nmlk.se

30
main.yaml Normal file
View File

@@ -0,0 +1,30 @@
---
- hosts: all
become: true
remote_user: wholteza
roles:
- role: shared/bootstrap
vars_files:
- vars/bootstrap.yaml
# - hosts: production_main
# become: true
# roles:
# # - role: shared/update
# - role: bigboi/users
# # - role: bigboi/network
# # - role: shared/avahi
# # - role: bigboi/nginx
# # - role: shared/ssmtp
# - role: bigboi/zfs
# # - role: shared/zfs-zed
# # - role: bigboi/samba
# # - role: bigboi/sanoid
# # - role: shared/powertop
# # - role: bigboi/apcupsd
# # - role: bigboi/libvirt
# # - role: bigboi/kvm-homeassistant
# - role: bigboi/docker
# # - role: artis3n.tailscale
# # - role: shared/various-cli-tools
# vars_files:
# - vars/vault.yaml

View File

@@ -1 +1,27 @@
# Readme ## Installing and running
Prior to following the steps below you need to set up the ssh agent to work with the gpg key from your yubikey and also the `pass` password store.
1. Install the required packages with `install-requirements.sh`
2. Run the playbook `run-playbook.sh`
- The script automatically fetches the required passwords from the password store
The playbook requires the user `ansible` to be present on the target systems with the yubikey ssh key as authorized key and member of the sudoers group.
The required password to be set on the ansible user can be found in `pass wholteza/network/lilleback/ansible/ansible`.
While running fetched passwords will be placed in the `.temp` directory. Any script that creates that directory must delete it afterwards.
## Making changes to the vault
The vault encryption is managed by `ansible-vault` + passwords from `pass`.
Use `./decrypt-vault.sh` and `./encrypt-vault.sh` to make the file into clear text and the other way around.
There is a pre-commit git hook that will prevent you from committing if the file is clear text.
Be careful because even if you have a non-encrypted version of the vault staged and the unstaged file is encrypted you will be able to commit atm.
## Generating passwords for the vault file
1. Use `generate-password.sh` to generate a hash of your password.

View File

@@ -0,0 +1 @@
ansible ALL=(ALL) NOPASSWD:ALL

View File

@@ -0,0 +1,22 @@
---
- name: Create ansible user
user:
name: "{{ bootstrap.user.name }}"
password: "{{ bootstrap.user.password }}"
shell: /bin/bash
groups: sudo
create_home: yes
state: present
- name: Add public ssh key
authorized_key:
user: "{{ bootstrap.user.name }}"
key: "{{ bootstrap.user.public_ssh_key }}"
- name: Enable ansible user to run sudo without password
copy:
src: ansible.sudoers
dest: /etc/sudoers.d/ansible
owner: root
group: root
mode: 0440

View File

@@ -0,0 +1,120 @@
# Frigate directories
- name: Ensure frigate root dir
file:
path: "{{docker.frigate.root_volume}}"
state: directory
owner: docker
group: root
- name: Ensure frigate config dir
file:
path: "{{docker.frigate.config_volume}}"
state: directory
owner: docker
group: root
- name: Ensure frigate media dir
file:
path: "{{docker.frigate.media_volume}}"
state: directory
owner: docker
group: root
- name: Ensure frigate config file
template:
src: frigate-config.yml
dest: "{{docker.frigate.config_volume}}/config.yml"
owner: docker
group: root
register: frigate_config_file
# Grafana directory
- name: Ensure grafana config dir
file:
path: "{{docker.grafana.data_volume}}"
state: directory
owner: docker
group: root
# InfluxDB directory
- name: Ensure influxdb config dir
file:
path: "{{docker.influxdb.data_volume}}"
state: directory
owner: docker
group: root
- name: Ensure photoprism config dir
file:
path: "{{docker.photoprism.data_volume}}"
state: directory
owner: photoprism
group: root
- name: Ensure mariadb config dir
file:
path: "{{docker.mariadb.data_volume}}"
state: directory
owner: photoprism
group: root
# Docker service setup
- name: Install requirements
apt:
name:
- docker.io
- docker-compose
- python3-pip
state: present
- name: install requirements
ansible.builtin.pip:
name: docker
- name: Enable docker
systemd:
name: docker
enabled: yes
- name: Ensure docker project dir
file:
path: "{{docker.project_path}}"
state: directory
owner: docker
group: docker
- name: Ensure docker-compose file
template:
src: docker-compose.yml
dest: "{{docker.project_path}}"
owner: ansible
group: ansible
register: docker_compose_file
- name: Tear down existing project
community.docker.docker_compose:
project_src: "{{ docker.project_path }}"
state: absent
remove_orphans: yes
when: docker_compose_file.changed
- name: Set up project
register: docker_project
community.docker.docker_compose:
project_src: "{{docker.project_path}}"
state: present
remove_orphans: yes
when: docker_compose_file.changed
- name: debug
ansible.builtin.debug:
var: docker_project
when: docker_compose_file.changed
# Restart frigate if needed
- name: Restart frigate
when: frigate_config_file.changed
community.docker.docker_container:
name: frigate
restart: true
state: started

View File

@@ -0,0 +1,44 @@
# ufw allow 443
# uff allow 222
version: "3"
services:
server:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1001
restart: always
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "222:22"
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitea.rule=Host(`git.nmlk.se`)"
- "traefik.http.routers.gitea.tls.certresolver=myresolver"
- "traefik.http.routers.gitea.tls=true"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
proxy:
image: traefik:v2.8
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
# Uncomment this line to test: https://doc.traefik.io/traefik/user-guides/docker-compose/acme-tls/
# - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=zackarias@montell.se"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/services/docker/traefik:/letsencrypt"

View File

@@ -0,0 +1,29 @@
- name: Add groups
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
state: present
loop: "{{ nas_groups|flatten(levels=1) }}"
loop_control:
label: "{{ item.name }}"
- name: Add users
user:
name: "{{ item.name }}"
password: "{{ item.password|default('!') }}"
state: present
shell: "{{ item.shell|default('/bin/noshell') }}"
uid: "{{ item.uid }}"
groups: "{{ item.groups|default('') }}"
create_home: "{{ item.create_home|default('no') }}"
loop: "{{ nas_users|community.general.lists_mergeby(nas_service_users, 'name')|community.general.lists_mergeby(local_service_users, 'name') }}"
loop_control:
label: "{{ item.name }}"
- name: Add public ssh keys
authorized_key:
user: "{{ item.name }}"
key: "{{ item.public_ssh_key }}"
loop: "{{ nas_users|community.general.lists_mergeby(nas_service_users, 'name')|flatten(levels=1)|rejectattr('public_ssh_key', 'undefined') }}"
loop_control:
label: "{{ item.name }}"

18
run-playbook.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
if ! grep -qE "vault_decrypted: true" "./vars/bootstrap.yaml";
then
echo "Decrypt vaults using './decrypt-vault.sh' first!"
exit 1
fi
if ! grep -qE "vault_decrypted: true" "./vars/bigboi.yaml";
then
echo "Decrypt vaults using './decrypt-vault.sh' first!"
exit 1
fi
./helpers/get-passwords.sh
ansible-playbook main.yaml --become-method sudo --extra-vars "ansible_become_pass=$(cat .passwords/bootstrap_become)"
./helpers/delete-passwords.sh

4
todo.md Normal file
View File

@@ -0,0 +1,4 @@
- smb passwords are not updating
- improve structure for users
- concat lists?

37
vars/bootstrap.yaml Normal file
View File

@@ -0,0 +1,37 @@
$ANSIBLE_VAULT;1.1;AES256
39383364616339613837626566326631616532613266333035366531613464623935643136373464
3038653762666136383332326663336135626561663934620a306366616362363363333863663465
31323065306464636237396236373939396162653066303562666536306239616461303261353538
3236333837323962320a633935653965363336333930643763633838346437653665633965373964
32643366363236353837396436646433383137633535303934323033386139343931613663383732
62376133626339393864663162343461376433313136373831353335316636663733363139616566
61333264376432343961626262313839323366396165353865653634306366373433623861643265
35373437666231356633663461643664353666643264626637633431363035666232616539343639
34333166643037303132613663313332393762336538646339643765633965333231383435653165
39356136383532656534663532623864636566383865613930316361643130643734303537346564
64633530353965636231376234646363623137623464383737333231353133313161393737366663
36653464333662353733653266376231313961306636643835363935633366326461633239383264
31316631356534386335613032653536363964333134333535343864323262646439313966643263
37353064656230623833613936326664323738646165396432656532316530343230643239636565
35346261303439623634393961333563343663383030336461613261326135653763656339636538
39353631316533386136646237363435363630646263386430363135336362333531323931383965
61653132353432633531323436353836306630623765376437333537323937663366623466643933
33343537383938616433393562646134316638366435653063653831636166643832643363356530
61343335636630363862633765383565643830343462313230636364326439626562303832633432
35663530633662303032653730313761613634386265316564366633626330623635626436366636
38396134386463626365623433623561383662623839356334663934393164303833393230323363
64393135616535336164626339643861623738613338616530363466373664363237653737333233
33373034346161333036393137323933353636383031646231623039346637653263366338376164
66326433373238646535643535633939666631396466663737633931643531333634316466613033
63613037346139663061356230393131343466623762313131326635353366313166623165353636
32656233316666323533393765336561336138303163396631623264303237313761653663323030
66653232626664616564363264396434306130363139613937383630346566666232306266653863
37383030636330313239613237336264396134626436626464326236386536333361313865363165
65376334353462616261326563656166623365363066333636616535653361323965633661333238
30366463386133303661656335393333343734633731306164643031343734353634333938643766
61366361616639616161383534373632323630336639353535383533376366373934323031623565
31316236646434623235656266643566363336346639613466386338613561396262383630383563
31346461363861316234316330633939623162613730343638376538633061616632623638353263
32646665663462323565623537323161663532333230373837356235303963613234636562323263
37336437333033356239373136386335666234393563616537386634336366383261346362303665
66636165316231633762

313
vars/vault.yaml Normal file
View File

@@ -0,0 +1,313 @@
$ANSIBLE_VAULT;1.1;AES256
35663239383464326563333164306264656632363761653263353635643630373034663239623961
6539346430323066366363666630633236643536333464370a633337373339306437666331633365
30376261636139393333626565656638336161636263303130306230643036333362313535613164
6365643464633139350a383131326266346564346235653166343334626533316232646331333738
36646330616661323436616538336463376561633963376430356434373763616539373234363839
63306665336132366338346264356565626462313633663733653830303738393061323364613636
38353435643164346235353931353338303235386533666264633237393433626332326532653761
30313462343131373237383064396131613764313831363236653737303833626138376161363330
37646433366266653436386630363366373135353232303538633038626461643864656133313735
62303266666566343533623434656663346337613261336231306631396637636662333132363864
39303065626633353865353830663430393361343736316534306633316636316365666436386562
34616265306663316438333634376534373137373965366439313864656135303132636134623437
37336231323036376466613634613565376533636563646537353038633663363065323839383338
37343533353461343761616636623061363762666338393762343130336539333037356664333533
38353634346430323339616466326638323633626461306266386631353533626261666534633839
36356537326130646535313439313137633430333931646561383730633536636434303761393962
39326432336235613561306135303762646466393561663963613162656538616539613134366236
61306432373434663033383438343864343535623865383539343361373533336561316334643166
32343065626433363962383038346239656237653063393935343932373666666561666335326239
37366631346534323463346664346332383732666331643435656537366564313963306331636232
39393032313834346539663866386161663762623632376632313132383135353538383533393839
37366532393237393132326666333062623631663664393534636634323431636633376638616533
39363435306637653862663366336233623637356166373133366138663961396263646331346539
32373866346139643136373030353535646132633335313432616338306637666630383938653137
36366439343735373864356434316464616465343933636135613562386234336164313663356462
38313832303865316262643761333165346333303564373939326135303636616165653035643164
66663039636366643661303863303437653638393539616130383437656438373066333831643032
38373935353163336630643964613862656438323131643764623739303331613138373631386537
32663363313361363163323033653039303630323931383563333862643662303434656263633339
64383838326135666266663236653161633863326265306566616231333463343034343463303434
34373833333436663932653438303937373738323363333534373063313939643534363265383936
66613561313763633637333335393234393262353766636362356538653430326232383734616132
64366365393161313766643065643763313732313865653436613731623364626261646232383065
35366364313838363638346365333465333339643234323434383562396630663436343965363135
63353664323534303263316433653563323864396366666236313138613537316534393261626430
35316538303938326634636561396465306566346238663266626163663962383064376263356239
64323361306238613830313039646539666465646563613537323038326264353263363464336264
35376536333933353434343866663331333665346162343137346235373465363066306164383135
66613464376136326137353037386136313030646138376338633232636165656132386263333430
61626461306363633563383965363438666231303734303432646133393163306339336364626230
36326439366433356636323539336262366266316364373039303963626433653239616163623933
34383136666264626638353337316264363537336161623838303834343333623832613630653937
63613539333334383637326237373965363535666362393336363937663265643537343865363936
65383433323964363461336465653165666430396538363637306266663537346236663362393638
61346564646334326464373936613637663930366663663433393264653631373139336435303063
36393464323566343335303464663535336234386634623766366163663036353639666332396331
62613736383738376666343263313039383564386238353761366330613965363365366563363065
30643964633664383465396561323932663966646139303533636138336264336334343663613233
63373765313263623239636131343030346438306533376562663365313532616266636637393634
63653464326138333862383864353838613836623862316437303262316338616335626566616266
34373962393634653665336130346438373265613662323138306265623666643762326333353936
64393931353835363137393063343461656239653265376338356430333731376339303935343963
34653830336336666337616462333336313132646339643164373565303539623033643935313038
33383134616531393561643838333731393764363165333733626166383635366636306462616566
62306164343333353462633534396362363236633231613339666335323137363338656462363338
65646334366636353235656334326239373464333961333239373561303866323761636632393330
35343463623533393261393931313932396664326164633036323264643365306330373263383835
64323864663939323537376462393534643362306532653330353835613664396161306163376132
64303732613136643939383165356532613832663066363839623739386161643435336335336238
36373934333265313933376661623766386561316331333733363637343336363337363261383130
34646266643161626137306464323462303766343962316563656338613538623131613361643930
33326166666562353836353537663434323761343266313636366436656661636633346636663934
34376266336533346231643831346161643630376165333736343430663738633965343234303131
34326237333636633134366463343537363632346561383137643437376332616462376265306462
32636637356665376139663337323234633563373437383063316334303336646134363766613363
30333939306663646532393938373932646239316662626461313561353065656437643463666662
61386435623235376332613039396164323366343664313132356137613662663163656630396536
64323136666563363339306536653438363230376564366436663161376230313336373764613461
31363861326631393661343031386532316139366161333437363665383434306665306333666661
34346331613465663330393535366639316433323634363531346633643737636235356361616466
35386236313433623366656237343464623836613131646432643330623366353666336534363935
34336661336237323531363136636135306664323566363034633363393665666430326465346462
33336661363831333837623539643135333632313038626533356333336566343162386237383737
65356239343138343131316132653137623934373165396366616161373364396636346364636664
64656338313831336361316539616530376438323430306433616532366165363832346665333136
36376566646533346261653631353039383135653631626135323736643966323538623366666266
65393632383235646261386439313763646466313364623839646631663137323230666135393938
31623464646234346563366537376430303534386461656366303538623436376132363464313930
39636261643939353431616635323764306537653539363939636130633538373739613234636331
30633266346537323136613163363933313930633661373164393035613335613230353762643034
35323631303337643365313635636230643137363031383061363931653131663930363137363435
63366530383363623839663134366365323235313836356461353832356562383437353063306463
35393539623263623531393133353366623332353365376365336431383339316461336265653839
38666631643133646431383738626337386163643732653933323433396138623539623564373931
32383637323833353631363730376564306137373031323038656534396339323030353061383234
62336434616239333464643763643432653434353061336534656234313339656331333563616338
36393033636363366434303561663632663961343861663431363033316663663835626539613538
63383932323235346562636164373862666165633932396536313836626464616232376139353865
62656231353231636462396237376630396138376432336265613362363332663336633165363963
32383336383066323032366236356536366466666166326165316263303933393634336534333163
38636366633135383930336363323161396539383933623331393235383538393931656666333838
39393931373935323436393035333934316635653365343731336637356666326334663461376532
65633033363835346230333436316664623366643836643730636237383864646131326265303638
31396636366238356433633665366534616433303633353135663436363365313161353537393562
35346563383436323661306338636231383937666135346362356239323835303130353037386230
63373336636164383465363633343962376435633739313233363132313531366535643963636636
32653938633866303430323030653832646463373261363262646462343131616338646632646334
35653330623564633235656262383861386332346265393436363262363235656661316431373239
61623533346561613435346433373862353035646361646630333537396561623062613739343139
63643364666665393034316630316138336139386666313530373363623535643738643961396138
31346362666361376633316537306332323833373263656237653464626439333834353739396432
63613637383965383133336261626239626633316561346234643935353431353566326262363139
65393731613638663837346661386665316637626561653866353832383964656634636561333434
38313237326635656664343062633736383262626433613136336566313164613633363962303066
63316165613830626139633538346130643462383737373565383435653439313032356430643038
30393638653434623566303932303038613033643965373737383765343362333835396661393162
33623835316537353331666139636165343561326238616635376438333739663235653339646639
34306635353836663939613564303739626138343131333536363537613637353063386535396234
61626333303665366463326363666439343865633164343630626233393065623162313963653238
64363336393630366463666337346131303234633835303831323562653039626437363830386363
30366136383064343237343862636235323837356536366664343166366366666663613339373065
30653765356537346666383738316231316238613732653163633761633264376336613339613964
62623638306436333266383937373939633762313533353366333461633763376566376166623531
33303937346566363563366561363363346631353262663236303364306630343536633034343066
65316662326130303336303131393966663962633632633162656364373637386333333530623631
65396565613562616132626238316666616262343562313033623537666163363862316663313337
32356438386633636437306530613934353539313137333238626132316439333736636437633461
62666431326565636234343263363635393937343436653630653561343635323934383437666636
65333830643031636564376661373538353138396336613134333332303530386466653538306466
62383934613131313565646434366338653062633839396664376664623662366432633763333831
30643135393434313561356565656133336638386532353332656133663137643161663534353661
35663964303535326633346564663464616338373337363632316264333665613962393065646138
31316535613539306233343533643130656266623161313436666566386166303635643037653536
33336161393064613733633262623932303230646137313464366433346238303533353665393665
32623731613632386265313831656638376565653236363231393462366162663933386332333861
65633933363838393730623165666164633762663537663238643530646337383731383663333864
38373939373562313330373632636238346532616635323362626431356137636661343536623532
32666335666434373462356366636163633431363530333233653430333864613266393964373463
30633537616262666365623137313164346231353438346566636238656332313331663433343839
36663138353964346662343030396630633839333965363836636462353361623635663136313731
62323564383933653966363233643566333132333037373363306239663361333336323366343738
63626137626233303732336165326231313064323733393635633133663237303534316136313630
36333530303764393035643163396630636561663330636662313639396531386635343666383138
33323431646339303964313538633035313536373931383564316261653136333861393935376432
36356139326233393536306261653031353665336535653766326364343230616531643038626539
62303033326639393530313066333063303639653630656538616234626465366564323731626462
31376533643637656363313537373664333864386164663464613631376661643630663938383637
63656537636437346161636165386166626633646166346166623039303737666663633037376135
30633838643765613831336132623461653031613937353765343431623134353938313538303739
31363833653432333237633539666333313264353239363566346335663634333031323761613861
35383863663566356133366234643763646161623761646364626337363634323762633264323638
33383837363131323230643664353730633634376530393064366264613332313837666165363862
37316430343063623032306432363638626562333331366131306236366337343734326436383864
35643739396533363161343764643631376563333931656335363063653833336563306438353432
34353633623764306565646531363031616233343565323063653133333135393332373262366431
39356261626463326436333066666433646461353333353763373664393462653737666135336334
30646338336136626438376564316530383031323236376364303734383738373431323035653061
31663938393566633261356266623762633066363563356135333161383965396263633262353234
39646334343238313635653765623234623436366565653961326163383539356134356430666237
31336466303332613634393939613633356534656166323533303839356438366662623361633536
34333931613762366239626538386130393435336365343233323066363637646238643438623261
30656637333237313166333666666566303362653566303462396533316165633964346665623137
66383365653365386563393835383962656430356232616666323166386638333236333362643866
32333566633761663463306535333361666632613735656139616537663563613733373336343164
35363738633535656535323136656637333330636337333962303765353666333961396434393138
37363434643766323639396631613935616236346339383530343737666463383664373563353935
39373165386162343634356630663835666261306637663234623930613532643439393531366336
36373361393037613533386430623438346439393664336464363564646166313533353762346532
33356533656364336438646363613737643834613137343666343465376537366337613839373031
36633836643734386361663861303266353334393035636331616236373532393862633936373633
37383634633861336264353430613931326337363665626364643839373263373633396239633961
63666566386338613436656437353666666165373832326563396630613235656236626165663664
32333464636461613238373564313137613265656634646139663730646135313866356565333561
31303338393536653164623261313466386331613231643461626530323065346434353964303966
32613137643939333435373938353537343061353639663838343931343530353035336366626166
66626635336231373136366162386563656431323661393737653339663066393132313231323133
63643837363731656138376136303134623335613830303138366538316232383565386434613335
33666633303135313238663237643234373434313132333665346663643862383436303063626133
66653132363938316337653735636138366163613266633663396666633463636531376330373433
30393134363039313435646162616432643165626135343939373936626230653134393063613939
37336639323133306463363035383865373630653833383265613164303262643737313731353235
30303135343938326432663030613265366136396461646465323330373537613466316439303531
30653562376230346563356336376135323538336564396563313966656639356331386263626432
64616639643436646434633532363239666136666333643535303263323737663332303931366239
37323338303361666664306362376165656537653034313436386563353531326534643630656131
33306364343962383334636664316335633937383766653265373334613530653935363431333362
30383332336339306433373266366137353066666533636261393835386230316535343437306231
36653162643638653138633363363561623330356139613666343564313563623336643937346466
64643963313831346465313138373462353331636665666332316163613337663435616665396330
36663539633763323835343862626361363030653566373334656362613636383234623235303538
37666163343466306365633863313332303661373234653734616439306537663563636239613437
36316339633034663066633538373666353834663730656632626466656639396331333864386666
30306334323139363866616432386366316361383935393863656138393731383163373863376630
37396335303930623136343463383634366636333138363562623435363639373262373735393035
64313831303737386566653362313639623261653034303734326433386639633363396163323033
36653765396236393238313964316530363539383431346261643234386531383132626565666233
63663436613239646135353331333338373236383262653932666135323963663039656535313761
31363538323338366465633233333833323438636538356132373133383031373734633039643838
30383035623631313935626563336265626134313937636434386461653930623831343332393465
37616338336461313839663737393637353663343034306366303535313538633036663665396366
30353237316331623930316632376534313236323633613565373934366362393337666431353434
37323032366433316137653761313338383962396564646132643735633334643034323837623130
36666262323135313430303434373830666464363734343931343338313066303162366439353833
33363935353637376666336562656365623466613838643632623434316238363435323535646132
38333363383835373761633265373465376131383265313733626662353833613662653535396432
65376535633530316464643938306436653935613264656131646233653133323035346630623663
38343162323164306535376330636538663839313937326638646231336231393035376165376163
62373030636136636532626334353335653266643763623234353061306437623931343464306164
34333835363962633964623363366466636635363664613238333662393536353561663937653065
37663062316461643161653464346230656262333035383665346438386464306462306135366230
39383437396262393930353737633962343564313338353034303362366637313065646162393161
39333461616339663334356130666630653663616563663835376330633531346430616135666139
39306336373366643035643163363130613538393634326330373134666563613933656666326463
63663236383464636439343832373839323966343766323639393038306435333738633639363164
65356663353139366263333661666438323165336162336439306263386435356161306162363136
62366638306331373634316636386239393164623662623633613366656463363533663830313936
35333233376664353365373235326265666639633366653037373135613136633065303465663037
34333439346436306365643630343338303533363036633361383036313362646332346530663538
36343736323163363261366331653862333034623663303261303064396134333738356562643161
62306431393039363263323932663437313864623266373163386337303438616461393536303561
34393466666364366434313430396636353061336263356134363763336133316330303664353765
66663964363539366232643636383438396662396461336165616237666565386462376365373865
35356262343034363439653564633762303965623230386239363538636134386661333732656636
35653937353235333434313131323931376630626132373561636236613936613539626263316339
66303433626133326262633632663765323137623135326362323531653839653835393034656662
31653564303830623433346533323937373863613234383138653339303036633039386237393663
35373638656439356164333031613166336435323039633164613937366239393736343039323964
31356330666165653164346263303437663738363766653334393332396163643434316635616165
35666632346538396435376530653930613838646435353539313931636431353830613138663433
35323630666266626432633335356531326331626136613534373366643762343831376461303633
38633663666134613062353962666630646239653135313835393238623961616232313136306162
33366462613538343465363532636337626536653062393338323736383130323462623933633166
34373963366635613131613161343432376439336163386530393932623537383734633132303132
33386639346631666332616465396438356339316165633866633266376335633433643337653364
63326232653239353063383266303733393038613063666265353235376531616231613366633132
38363639353739383737363864613732613166316137363666643266643239613831323432633332
31626166643739333261343066656634663531316639353338376230643037343837653434363939
66386163306339376630633266633830613639626334363362346630613139653165373037313361
35356463616132623036636639643536623637303333653131396432626237333335366336636663
35323262616339313533613730303766393866613536336530383763643662663635336266613664
37643462363431333236326233323534383735393630343364333462613764336532643336366232
34333161393765383530363437363862663330316139316432393334353764616362336430613538
39656263633932393932643031343866623439646235313634626339636437366663663632313232
63363363306236396336373134363836346265396261333466343636343062373932303937336231
65326166636531383837306339383466313763386636663432653833323333646133616132643532
62633936346262646430333861616636613032666236636164626531363232353863396231656437
37383638336536363363336432363335383465353136313237623837613163633535383137663038
31663334616238333762393463373662303637353435376139366130303230613261313364313139
38333361653238353365343937323263663234663633663466346530353562303362356236333137
36323231333938623034623936373764363333613830656264386536666465386533336265393365
61366232396531353361343131396166353633653564373164663636363861373630346530376335
62653439663037613866383565626536656661316134383535323638663862363733386438313362
63396433333461373636306137313736356338653261653866366530633561636338643865333763
30653736653138333064653737346464633038303439653734353562373137653939336462633039
30306365643664343230653136336666373631343234343238363362343438653466643163396163
38316338623365366232316165313030323931373734663064306636356333633333623561646338
39333238373766363963663238326564343461363731386630303332643131326465613466323637
31636530383966633136343832323966623338323263323566303934653831613030356337313230
39353434636136653133653165663438363638396133666332303631663166373864386565623061
63363264623137623365303266653166313234663461633263316139633430623736636363343136
63653937366363383065363763353663643162333766356465386137373161333765663566656332
61653433346335356463663661366636393663646164616435396235336631613266313131643064
37626663656564666264303262303139626136333834666465656265356366666330346364363963
31643863353464636339626535393961346432663539316139336130663066343239643136323163
64313139373130353165306230316138656462366231393663333834643239306434653061343339
64396234343037303462303637323364393738613063303332386333383036353434313462383037
63386564373366366135316264663934636264613137343331666135363561376636343562373233
31656165393937383662663733333936366534633261663862333233343563393631653462376166
61343434613561643333626635636562313662373563346665303635623936383732636433303863
31373136343830633938386466306231353563303262303865363732623334663466393331653432
33373932616362633838326562303163613839633833343765633363666138303538313564626562
38343366396264633335326364316261356337336463643239323939363561303565653536373665
39643264643663343866376538343362353165656233383031313834656234303863323833313831
65323431643537336363633065613730616134343365353762306465366436333632653139626265
31646565356562626538366433323537666438373465623337303733653466623736373730613838
34356634393862613564636239613666313364333631303738313566643465653236343434613862
37613762306639623531363963303734393764396634376335346534376265383435393862363862
35643761303964373538613762366330303166656361633536636637376131333839303861363131
63633562303637306264613166653962393564356264623038323865616535623762663233376531
32303131336365373139333461663638643932643030616439646635346265646335323339313837
62646139326336316239333436336437323764356562616461616662333033653033383764363262
64643966316335393536343733363736323666333838626537396337306363633336383335353531
62653466613762666662616434613432333237303332313035323737333430663034636563373233
32636261343634623337373436663432323035356162316365653166623839316235656537626162
65353937393634303036656339313739386564393435346264613564653063376334313962646334
66663531303339663930643034613266393932653230306463316530656238626335373562353933
32356437353961646638663666323363393334623731633861373339366131383563663531663033
36653263656232343839633466303133353862306262376436666339363636383663333638663137
65333936336635396435343361616162356232363131663065633863623262336164386435353331
39363965343831336136383562643565633630666266626337396439303264343133613664366339
66306363646538373839646539326336313536336165666130653434323033663632663562333130
34313833393431616462393864363366376535303835306234333762333366383035326438343734
64396563636361643833343766626162313562303235636235386337636630393335383334636261
30343364626432343137613064373032303933363234623037386564653331343734356562643939
62336230333538323933356235616234623931393035633865396161303536396235376664626665
32396230323738316136386565346466326139646534336436303635323330616132643634323366
32656435313565316636333666636465383037656334303037313433376462323439323734313437
66636130313339363265613362643039323736313531373030316532353466396566646334303836
64646466336530636538333939356136303939656564643063336465336230386633626430376131
32333735323235306131346339343533383834343137646266386139373234633035303236333030
31303861316266613437393362366535323930383463396538353539313265323364613665383333
37663133303465356532633139626665343234366238313632653136333634346136316132613234
38316337656661396465646532666135373664303532613134646239313333333932346339656137
61356231383835353930316334353962323435616663326339636263316436643439303930373335
62343038623031643033376162386164313939386638316639666363393730353863626631363833
63383831313430353430646137306330386465346339613238616632663338313938343338623863
33623636626530646132363563363839626563666330636132613063613261396136326539353835
30363564336462393832666135623239616139386635613363346463393437326564303563386131
38643936383339393634663062343661326562613332336362616565313962353231623664323463
38316666316639373262343137653437663433656362663434306633396661373631313962306135
30363136373039313833333733343932353462316632393364623665363834636137316464623538
30313830626538633932313264373065383339303638333739353066316363663436303736653135
30633966633463356161336536656136663234663563303138343633303766653562336261313462
32316566343833383632383763306538646231656564656437333437333738396630376562656264
37333135336630376239323837653635653361656537313565353938653734643834316565656436
62333636323532643334636631363630323933613636326135366636323365646362313061373261
38396262646561633066373939653239323466633430633731383762643163376531656236656363
66386532653831633732316630343236396235303038646432393964363763313036383463353633
33613065373461633631313437313237623332356639323235336164393864313062663363303035
63336362313233313639303462616234333031653261646461623034343136333538326139643461
61663266363631653366653935643431303566666133643632333231623564643636636334343366
32376435616663393963