From a72b3d36d72129711cae7f8d6220cea0c43064ed Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Wed, 23 Oct 2024 13:51:59 +0500 Subject: [PATCH] Run nextcloud --- nextcloud.yml | 11 + roles/haproxy/files/haproxy.cfg | 15 +- roles/nextcloud/meta/argument_specs.yml | 31 ++ roles/nextcloud/tasks/main.yml | 43 +++ roles/nextcloud/templates/config.php.j2 | 59 ++++ roles/nextcloud/vars/main.yml | 18 ++ roles/redis/tasks/main.yml | 5 + vaulted_vars.yml | 374 ++++++++++++------------ 8 files changed, 374 insertions(+), 182 deletions(-) create mode 100644 nextcloud.yml create mode 100644 roles/nextcloud/meta/argument_specs.yml create mode 100644 roles/nextcloud/tasks/main.yml create mode 100644 roles/nextcloud/templates/config.php.j2 create mode 100644 roles/nextcloud/vars/main.yml diff --git a/nextcloud.yml b/nextcloud.yml new file mode 100644 index 0000000..90685df --- /dev/null +++ b/nextcloud.yml @@ -0,0 +1,11 @@ +--- +- hosts: webservers + roles: + - name: nextcloud + instance_id: "{{ nextcloud.instance_id }}" + password_salt: "{{ nextcloud.password_salt }}" + secret: "{{ nextcloud.secret }}" + db_password: "{{ postgresql_users.nextcloud }}" + smtp_password: "{{ mail_users['nextcloud@comfycamp.space'] }}" + url: https://nc.comfycamp.space + trusted_domains: ["nc.comfycamp.space"] diff --git a/roles/haproxy/files/haproxy.cfg b/roles/haproxy/files/haproxy.cfg index 84378c0..f35998a 100644 --- a/roles/haproxy/files/haproxy.cfg +++ b/roles/haproxy/files/haproxy.cfg @@ -33,8 +33,9 @@ frontend www acl host_mastodon_tor hdr(host) -i mcomfyzeyibt2unmkttoxa2li2dzpsljcp3sasrioqsks4ayrl5kk2ad.onion http-request redirect scheme https unless { ssl_fc } || host_mastodon_tor - http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } + http-request set-header X-Forwarded-Proto https if { ssl_fc } + http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;" if { ssl_fc } acl host_mastodon hdr(host) -i m.comfycamp.space acl path_streaming_api path_beg /api/v1/streaming @@ -56,6 +57,13 @@ frontend www acl host_authentik hdr(host) -i auth.comfycamp.space use_backend authentik if host_authentik + acl host_nextcloud hdr(host) -i nc.comfycamp.space + acl url_discovery path /.well-known/caldav /.well-known/carddav + http-request redirect location /remote.php/dav/ code 301 if host_nextcloud url_discovery + acl path_well_known path_beg /.well-known + http-request redirect location /index.php%[capture.req.uri] if host_nextcloud path_well_known + use_backend nextcloud if host_nextcloud + acl host_comfycamp hdr(host) -i comfycamp.space use_backend comfycamp if host_comfycamp @@ -147,3 +155,8 @@ backend authentik_ldap mode tcp server s1 authentik-ldap-1:3389 check server s2 authentik-ldap-2:3389 check + +backend nextcloud + mode http + option forwardfor + server s1 nextcloud-1:80 check diff --git a/roles/nextcloud/meta/argument_specs.yml b/roles/nextcloud/meta/argument_specs.yml new file mode 100644 index 0000000..37fd5b6 --- /dev/null +++ b/roles/nextcloud/meta/argument_specs.yml @@ -0,0 +1,31 @@ +--- +argument_specs: + main: + options: + instance_id: + type: str + required: true + description: A valid instance_id is created when you install Nextcloud + password_salt: + type: str + required: true + description: The salt used to hash all passwords, auto-generated by the Nextcloud installer + secret: + type: str + required: true + description: Secret used by Nextcloud for various purposes, e.g. to encrypt data + url: + type: str + required: true + description: "https://example.com" + trusted_domains: + type: list + elements: str + required: true + description: "example.com" + db_password: + type: str + required: true + smtp_password: + type: str + required: true diff --git a/roles/nextcloud/tasks/main.yml b/roles/nextcloud/tasks/main.yml new file mode 100644 index 0000000..a660714 --- /dev/null +++ b/roles/nextcloud/tasks/main.yml @@ -0,0 +1,43 @@ +--- +- name: Create docker volume + become: true + community.docker.docker_volume: + name: nextcloud +- name: Create redis container + include_role: + name: redis + vars: + preset: persistent + container_name: nextcloud-redis + docker_networks: + - name: nextcloud + docker_volume: nextcloud-redis +- name: Copy nextcloud config + become: true + ansible.builtin.template: + src: config.php.j2 + dest: "/var/lib/docker/volumes/nextcloud/_data/config/config.php" + owner: "33" + group: "33" + register: cfg +- name: Run nextcloud container + become: true + community.docker.docker_container: + name: nextcloud-{{ item }} + image: nextcloud:{{ version }}-apache + networks: + - name: nextcloud + - name: haproxy + - name: postgresql + volumes: + - nextcloud:/var/www/html + - /mnt/hdd/nextcloud/data:/var/www/html/data + recreate: "{{ cfg.changed }}" + loop: [1] +- name: Schedule background jobs + become: true + ansible.builtin.cron: + name: nextcloud + minute: "*/5" + job: "docker exec --user www-data nextcloud-1 php cron.php" + user: root diff --git a/roles/nextcloud/templates/config.php.j2 b/roles/nextcloud/templates/config.php.j2 new file mode 100644 index 0000000..71182e3 --- /dev/null +++ b/roles/nextcloud/templates/config.php.j2 @@ -0,0 +1,59 @@ + '/', + 'instanceid' => '{{ instance_id }}', + 'passwordsalt' => '{{ password_salt }}', + 'secret' => '{{ secret }}', + 'version' => '{{ full_version }}', + 'dbtype' => '{{ db_type }}', + 'overwrite.cli.url' => '{{ url }}', + 'overwriteprotocol' => '{{ overwrite_protocol }}', + 'dbname' => '{{ db_name }}', + 'dbhost' => '{{ db_host }}', + 'dbport' => '{{ db_port }}', + 'dbtableprefix' => 'oc_', + 'dbuser' => '{{ db_user }}', + 'dbpassword' => '{{ db_password }}', + 'installed' => true, + 'mail_from_address' => '{{ mail_from_address }}', + 'mail_domain' => '{{ mail_domain }}', + 'mail_smtphost' => '{{ smtp_host }}', + 'mail_smtpport' => '{{ smtp_port }}', + 'mail_smtpauth' => true, + 'mail_smtpname' => '{{ smtp_name }}', + 'mail_smtppassword' => '{{ smtp_password }}', + 'maintenance' => false, + 'loglevel' => 2, + 'memcache.local' => '\\OC\\Memcache\\APCu', + 'memcache.distributed' => '\\OC\\Memcache\\Redis', + 'memcache.locking' => '\\OC\\Memcache\\Redis', + 'redis' => array( + 'host' => '{{ redis_host }}', + 'port' => {{ redis_port }}, + ), + 'default_language' => 'ru', + 'default_locale' => 'ru_RU', + 'default_phone_region' => 'RU', + 'trusted_domains' => [ + {% for domain in trusted_domains %} + '{{ domain }}', + {% endfor %} + ], + 'config_is_read_only' => true, + 'ldapUserCleanupInterval' => 0, + 'auth.storeCryptedPassword' => false, + 'maintenance_window_start' => 21, + 'apps_paths' => array ( + 0 => array ( + 'path' => '/var/www/html/apps', + 'url' => '/apps', + 'writable' => false, + ), + 1 => array ( + 'path' => '/var/www/html/custom_apps', + 'url' => '/custom_apps', + 'writable' => true, + ), + ), + 'upgrade.disable-web' => true, +); diff --git a/roles/nextcloud/vars/main.yml b/roles/nextcloud/vars/main.yml new file mode 100644 index 0000000..da85c9f --- /dev/null +++ b/roles/nextcloud/vars/main.yml @@ -0,0 +1,18 @@ +version: 30.0.1 +full_version: 30.0.1.2 +overwrite_protocol: https + +db_type: pgsql +db_name: nextcloud +db_host: postgresql +db_port: 5432 +db_user: nextcloud + +mail_from_address: nextcloud +mail_domain: comfycamp.space +smtp_host: comfycamp.space +smtp_port: 587 +smtp_name: nextcloud@comfycamp.space + +redis_host: nextcloud-redis +redis_port: 6379 diff --git a/roles/redis/tasks/main.yml b/roles/redis/tasks/main.yml index 98260ac..b8b1a46 100644 --- a/roles/redis/tasks/main.yml +++ b/roles/redis/tasks/main.yml @@ -1,4 +1,9 @@ --- +- name: Create docker networks + become: true + community.docker.docker_network: + name: "{{ item.name }}" + loop: "{{ docker_networks }}" - import_tasks: persistent.yml when: preset == "persistent" - import_tasks: cache.yml diff --git a/vaulted_vars.yml b/vaulted_vars.yml index 9852e33..7f9c772 100644 --- a/vaulted_vars.yml +++ b/vaulted_vars.yml @@ -1,182 +1,194 @@ $ANSIBLE_VAULT;1.1;AES256 -37653938626461363138383333646263636164656664656231373239643065636334323961373563 -3137643265333762626636343035303063383765393336380a303736626138616464666133303538 -61663535633664303363356431326462396465363139616335353364366436333532626335666465 -6636373466363038350a303733633439306330393931373566623838666332363935333236643331 -32646666313833353232373463623133313133633761336134616534613165373836313661363733 -39326262333262333466353966616331623230343765336431393832376231323435383431663563 -34353833343537343535646666393433393433333637643137333763393261616664363236333563 -35353262353434643862326666303061333236373734343236313364663963626465643835626232 -31303437396131656161653730626563393237383733383339646665613530333066613263393434 -36386633633161326432616632363934363539306264616337393032636334383831333339373266 -33373836303439623131393235666531303130333464666365363336313937323538356633353431 -35353133353764653234356330616366633439356665303661643738346637316436313035353436 -35653766386564316430386635306665633038363330313365386539363735373862326461353265 -39366365383931303662323934653035386332373132666265353561623038653264303735636630 -33663966636131386536396135333839393732633264356333383864396131636364383464313934 -38336564303234386165663763303436363961323435333563353632336464363461386639313839 -35666530346237306432373039623936613932396166303431336635653832613733656535386666 -61333938393739396530656365346230343330383737623761343331613165336631646232653130 -37396639366630646334623662643135383566656133303263616538623038343338356237333862 -30306231363831313461373062366430633930633233333133366462343436613561666139613437 -32613130636332326233626663313064663132373462643331396530646636376363353934613463 -64373335303163633231386262653963346365303161656635313930303261633438306665373633 -65633864626235366638656232363332366563343535313334663764353937633731353432363033 -31396634616535643566333736363036313164366535616433616537393734326638313933623835 -32633933613365613264656432653065306531643562666336313938636131623738643965366635 -38383765333433643164303335343963626135613666666263663936386438663763316337353365 -63636362366331383634313165313466393437666134623734306632373238383561353364663930 -33636264343332373330633962393530316664373061306436356161613164613230346564323332 -66663433376465306133343866376438306164306435393233636238353331646536306161643131 -34323937623263383165616135346139613339633864393138386539353133376262616437636161 -31653333316332343463613937393963346331633134643332383130343635633731373764643763 -34393832643531316234646137353435393633373139383065363436346264613334383861326139 -36633739633661353738363134643962363162333362393765393332643864323365656634653333 -30396234666264313862656631633137306431366466653835326337393433626232613139616161 -31313661613235613163393139666162373934623737616464653137626665316436373437383964 -37643833353161636438623033383839616438626566623166616636626535353137376338346532 -39326361666164333834626533386461656565623430623537333133343665396564346465383831 -37393232386430346166373464363265646139303737396363653034386462383038633030323137 -63633034633133666337386331396531343338383534353463353237666437666236313736663536 -32626461643866623565613431646162656537363239623264366631396461313434313839326538 -37386635623233366164326430396263366438356362396336386134333264313734653630613437 -64653662636538646666326633306365646435383633353433643637336331643037343663373931 -36353363613036306636336136396333666437353965633531653863356235666561633536616639 -34643739653439376565346262343936386532333338663963656638353062333365383933663139 -35643165363136366634343362633864333936626364316131303937323261353563653666636131 -35363663663066346663636134306663363435633261383464383236306539303031656235323166 -63363435323165353431643962663330633432306131363430353538396535396537363264303131 -61303738336562363661653664613835613163623631396665646230316163623162613861386562 -33336432303836623735333066666138383539356263643035326634373834333765643063383738 -34353264363536323134376162383166626363366539616263323530313638313064346566366637 -37333133363265386234623161653635623130636362313233346534643830353433313761313637 -66666433633139353531326664376631323133643734323032356161316239316132306465643637 -33313933346165313561656139383233306130306538623966613931386564386335373265336563 -32613332393135346436646230343930306339623666613830643436636130353936643361393166 -65306432633831623438343138643166643864633930336634626633623230613263653537616266 -37636636333663326331343939353333303230323066376635393336306163326431336366396639 -62653934346239386233313639303737353236326162353866623938396533623938333164383130 -37343331636363376565386361336632653138613233303366616639366431376538333864653536 -31343832653065343363336136383363613361356532376537386138306639383835323263326337 -64663930633264303065363935613034613961393137366637656236376562366663663835393032 -66396365663537373636333334373931353634626336303439393366396238646137393665346361 -32343730343738323934326662363161323735613135613135313930383566333433376230383438 -61656139646337366466346535646462613534353536303561663165306437653434303662313462 -66306265633564313132346235356331396536333034363838393361616232323663653734353430 -62646365346130323663353436653763363362633535666464396531373331613737393632393865 -61663231333536363639316631303936343438323536633861373839346331343632623036636264 -36373664666431633837326364623864336139653535613039343762353038656165366338396638 -36353736613464343065633865323363663236383062656464653431393061366437303563666266 -38353865653666646234613736393938616165646563396538346665643632663464633035373864 -66626539383134346538623931373331646161306266376566376163323961316263353665636231 -35653638613763303233363963313937363961393137343338396634363233376633366438633637 -38343066313036353039313330313237616362323463396335343335666434333962653763323466 -31653663306565633531636330623433646137623962373435623663343635396638623764346338 -64643466333363333663393335353836366533366630353262343664363237633737303637303137 -31336335616639346266356636633166373464636363656532623865393438623964396463616166 -37613331316361396639386435323531666231613936306261303039383931323330633163306636 -37343463653230646231363061343137393364356637383964303936316339353439643635353366 -62323139626333373434336566633531653264333965366134663734326136646530643965316264 -32316631346235363237303264633033356334653339643731336133373262366433376432313639 -36333262373236373439633639336435643963633033393764383936613866383931613836633765 -66333530303964653662386236313331653031613735376263303334663061323032376238646139 -64393362336236613239323533396435336233353064663239393132373031306336623231346539 -62323965616164396230653532376362643037313931626334303263383831666462623663323039 -32316263396662643438376563663438623833363037313834623835323962353234656663393633 -37646439613637626532633339623865326163376339653737333063353630383831626639313162 -61616166356363326338303832346434326564616133643534366233316464386264636564613534 -63663266656230636166343861363235623932303434663438366335373061613166623031343563 -61613434323030636136623132656363386539383837626137303132653837333861646461386437 -63353963653665386566623066326266393365396138313536313738323161373364396261316236 -66663237636661366336313765313433303237623933306365363634396430623430383934313731 -32346533623437643538663930653761636265316632323166323930653862623331313233626230 -33613330386533623963383131336661303666333432323434323830366537386238383039636566 -30346533336337636162643866636630663034353135303565353461383765303864643666323634 -31343234383436613738626431643161373339646166316431626633323832613864316331376465 -39306234393638356663313636366263616130663163393632353234656263316264313330336563 -30343564633863346630636236616664636165373862396233353032346237316262383239656638 -31346565346331663239366465323430383539643632356363323564356337636264323262633235 -30346435626363363736323763376231393339653662663734333163333031343361373934383633 -37323538613763646232663438663136313136323363393865383336363261613665613564326133 -63306231393438376630366162646132616131646363353937616530386331616337356433663438 -39316538626264666162343961393332313364303566323234623065376434363837646134376164 -66626531366263653233306432313236303033383131636165363232656163376466656232663965 -38383666363061636436333564363136363164613531383562313464323139306436343131306137 -62323238643935616438643235346139343533626364306437653234383661343862363238613333 -39363234366433646136633236616363633761326233373961373632353831376263613365386232 -61323464366239666430366566633261393564356338396438653162663433633138343131363430 -62383130646136376461303839653662373535633637346661623238336239616132613735623839 -31663332363531366161303734303833306264356636623432393561393966666639363733623964 -65323237616136393265653564383038383138376234316334313463383338356336343863383865 -33323862623830313238343633653663323763353335613032356461613264666464613333346163 -31363331323464656530663161316663363539376139323761383335653332616338386230373139 -35313332613732363663313063666361393765326531316635616465373966346132336633376664 -37366233386136643263643765303939663331363031396435633765653034373234316663623662 -61626662616633653663373639613235336136303033666264393133643663646630353638623561 -33363462323962363062386233393862643234646330663163303762366661663665616334643262 -35653666363635393431326464383365316336626133386165663561346633626565323038353339 -39343661323136313934383764633739366235326433623339306162313039643037663262663331 -32623138353731626164333862353663623163346263643535636561383265643932353630396237 -64343536613231626636373463366639323964333866386333643332376236663461646637343537 -30343839356462363338636336636537326363663964366534356633626335396437376265366630 -33653362363435313837313138346334363936306163656337396639333534323264303062663234 -64366134363330343663363261386163646366626230666336646133306436306430386431333237 -38336330323164653035383132383766313133653934303666306438636336346234623865393863 -63303166303632316432616336626233316663636139383963616165306230363936333962623566 -39626337343735376333336535386665396339616161616133303964333463373962343033633738 -64333063376236383434376262393531663366643365386237366237623339373633636564383739 -30306231353530346334343261633136383932306665393562666632313232333666303338653339 -62343666343366613063373166396664313265343938323165303661623964656534666231636136 -66613630666439303331336661626430343537656430353330323533353062653562373739663165 -38383566303666666338303664663437663533333262316430613061383131373538323332623432 -34653766633661323638626638636136663265376634316564373936343761363838623937376361 -31373466343131363136613338643939646165393261666439656132666535626364623037646662 -39386663383661336131313537373336616137356333643965393862306262366561333336396430 -65323234656430356465623661323137386134333133356365653238373362393235373233393039 -66333665313233393139376331663932633733343533356464316565386330363663336139363565 -62333531323539643439383733373066343630363061363661346139383935653731313264643163 -62373131393330323465616132356162373638313462383131386238636635613938373137313931 -31643637653039363430343032333262616161623835353639343062303531333763356430323066 -36326437333830643736366536613331323030666237343139643430363831313639386639643733 -31346163346437626465363461356137313833343461633139366463626230326466356336333164 -61336133343164313537633632633735333066663937373363646630633162666534366636346339 -66373338363432376635613964666663383233666261613539613237386361346463353065303836 -31643131346166386163633061333939306637376636386538333265326366343639323037336332 -31303736323335363232383863636437346530333837333666373836313962376666353136396662 -36376137316430366134306238396439386333613639376661336438303863663437393036303139 -35393561343464646332343530643661643633373531376565663431363534646431643838653737 -30666235613638333734653761353239316432333533316531356434646162333431636331306232 -66343863666237353538313036393637346332663830626361656162326534363735626634643030 -64393465643061386339353262656435333166373932346530613635316465616364646433616336 -36303332303038323262333230343035353935376331346263356539313566633036303639366564 -35306631653665393162393832313866343261343330323034613130316664303131363261333033 -62653439396665383531663233373366356630653830323236306538346562333937633937333839 -36616233613636316464336164333530613238633837383135663765626163366161383131373538 -36356264373261636666336133626138303032653935333561306364636164393163383064623934 -32313532663437383135383763663766336336356461363230333362663864616166393961373636 -66363135656530303361353234303765393134333264353135663738343534396630613136666564 -35666439663031656165353337626234653038663631363034353438666130646639616538376662 -61633963636631336432363663393936303364383836393566613638613132393065393735303336 -35653934383337366631663931343063356637383037633036303030616136373864643930306332 -32623263316466616132646161376262346137346335646331376436626236346136356165633037 -34643436393766663130643764383832333635356230613933613835376261656530373864313935 -62646132353830613366656630363232646634313366353037396462316336306435656337323265 -37306265666533356337663137353832663963643735343436646338393865316463343265643937 -61613431356631333163626232623162336130323331626162343435396662636563356465666666 -65363636343930383238363164613362353261383938363334373134363136383731366232393431 -35623834356335343430346164303566633039623862323066396535373265373430633235316361 -35303738663163653432363436626462613832653435653166646464343237356130373062386630 -31636636386137393764393335343435373333333933326437313462646331613830613030663239 -33636638643830363439366363353965666531396361313061616433636262633162303231306565 -33303233336264626336663335313861666262666137343734316439643661376335336539636566 -39663937303833356561636337336131613461613432393462353064343063313036333138636661 -64303636313334336236626437366464396237316630613736383436313032613437323835626633 -65303637313062383062313639313438376333653032376437343335663663663161363939643035 -38346532643938373637643035356236396136366466636432346433326461616439376333373065 -63383539386635366637303462326230663631313931343765363635346663653761306266343462 -32373365663531323566323836396464333838303239623962666635353638336565653535366637 -63393734356639366235363163363062336539346531643934333365656466646164353161386163 -62613536343362373833336434643337616135326230303434663432656166306439373261313937 -31333631393333643834323634303933356532323331663135623262616565393766393538626565 -36633166336231656637613535333964323532646139316132373662303566633535333238323934 -37623465356236393236393138396263306432303936643764386433396263373137 +35643261326366646231323831356465646461633330613761343534356630386361653161326166 +6162623665363762346265333931656339373965633266660a653562626636636531383666343861 +31373434393266363435613031633832663739353630663063326436346335356334623765343036 +6138343365306361300a353830613939323462303466303064616233313062383865313031336466 +34343366633664626164666266643864313566663139396166656166326439303964633764366562 +65333835636638366237386365353532343364343439613533626464316134353038383564306438 +62643265653863373538386430653539316530656638636639373163356331363662613661353061 +61373833306561616231656537353633313330623261653130633765653238333162356463386136 +65623930396136363035616530323161366564393836623665666638313230646137386264356238 +38303732333337386464656132393839376164666162383032306135363364656661656566353264 +61323633636432393636346464666661396139303939313835346335626337383966356235643433 +64356437393266356161346164313630656665323765396336666636653735396561306335356262 +63366366396362336334666539656663663166363263346666643962386435313237616666333065 +36313933333130363433363162376536643733313833326639383832643130333639376562643130 +64336363356437306239626130313035326630356633353964313339356238663664643631666436 +39633761663461343233383465366131303264386538653439663161343830356136303365366564 +37623231356538386439653935623662663038343865333130663063636435336234623366393231 +39646130373365636438663737323633396239643764646339383837643864306230663738613032 +64383032623236646133333437633934386266653233396631333734343132646465626563623138 +30643466336333366337626231626166666633636137376136333834373739393636663031313465 +35376137336438623765313666656332393836653761626632363632383862663435393937373935 +66336332313431373066666439623264343061623238666465356537353565373831366363313463 +66653439623866386636363531626636316435393061636463363339383262633066333731343039 +39306663616339383035373539656630666634393733383839383539313964346164633639386661 +61336662346461633831663062356236663365346238303963656636633438396562643430623265 +34313964613137666263336565336366386362383663353264643039336533666533343831326631 +34306164633332663035343464633732373662333338373561343463616263626463666465613263 +61346432663832653063663361346234363762323334353638313066633537626462356631393631 +30366637336161393838666666366235646134346331663164383931303063623438363235343738 +32366563666465346536643363393862633061373363653834313534623438353335303930353834 +31663038303834393866623332666366316163393534323862633036626562653061366661623566 +39346336373838636466626138316165336131633765653035656430653034386433376463376339 +30656563653364666264343339633830663466353666323635343635383464643033313735383461 +66643035383530623162396632633361623565363662393532623035333162386534653335356132 +64356138393130616131393530303831306661666138386461386165393237376165346339323436 +33313963383833373333303638313536393131313734363239656466643661303439336535376337 +36613630306564633831623139633935663531396137633461383066663539633263373235616231 +37656231343264313937373561666563656530613232336663313030643765393330633162393438 +63623838626433333939663339356463393762323764333038316161356437663566633831663065 +30336336366439356133353035633433663962636365663236663739623834643962393834613765 +32326662306239613766303032636563313737333034323665646534373535326466326263386135 +61613363653630396266613331336262643034373135653033346365616666343432343730313562 +64383963333735366233336638666632383835363236633330386136313663316362353535616339 +62613730306662663832613564306435333633323262363461626130663463343765333866383238 +33636663356566613230316465313761346536383935653935393134306334626330643930353333 +63643762303531313131343834376665306363396137333062336431306238616463386135313734 +35303934343361613930376664653065353965616266343337656161386362656564656562613535 +63393835346330653362363864373331353335613934366435346161303566616139386665633539 +38373730303738626163313539656339663938633432343464653833653161613163336236303338 +35353632396662376530633461646464363062303932393961323238386265623735356535613831 +39383637363330333337313864623832643534633130373866613562643631646464356339313237 +64613466343966336361336337383766303736653530356636363736326637396266316531633131 +66333162623537343536643263633430633634326437376662633136613464373135626139633439 +61373064623235326661333466613961336637626433393539656531633763393065623232396161 +64623132623061663139626435643434333437373166366230376361333030613337636133356338 +38643739356162376638363230386438336334363732393365333465393039346531313136393465 +37303935386266383564666237383738336362653539303866633761316231643033393733623834 +30333564633961613137393664353061653363393531383161373637646530393138366361313965 +34666637613462376665353839313230396435373334336231396538393939663933396130643632 +39653930346530646335656461393334656461336231383433313764666161376664313339373533 +64316564366434376533666661356636623161363365323535653366333135333634666536376631 +37393362633665663433303333663936393836336664323939393235363563623761613761666532 +33393331656433323431636339393831396133363665393464393238646433636637323131303465 +30663734663932623832356565626166626137383633316163323030386438313265353230626631 +38356438656665373535393531333035646464386463396434623238643837366437343865393132 +61306536623666326164323665363064663963376566323634643832653238616137366161356463 +62643863343436343537303565316165353235663564643231316564646132653566316339346438 +30303263633330656330643739383539376638383835313864306639613363383862616139386663 +39343039333261656663396139656431366630656134613665623335666563343130653739613132 +37376238623262663230333239323338643561653538353265623536306366356665636237633531 +61303761623832373136326334646462633063613733666463636136393962643961356634623263 +64366434333136656331663731356435313834326666643137623366343632313839373739373233 +66363831623964656338333235363935656439316262663762306131306166333233613164343838 +61396233386630343236656334316534363631303337616635336434373431383461643837376332 +39336461353764343539303034666231303336333132636637356637393938303364623030373130 +35363433613965636135376365306565306431666333363961663639313862396363336535663738 +36383464613536633333626365626161663633303661653034613664363861366133636663643064 +37663936376532356330646266656638653135373665653733636534643737633765336132613035 +36623737313366393133366566373732636535396230656436613035626232666162613233613066 +65333539613965623932633431653633396537643932343762623564363737623432613335373935 +36643638303533663836663533626263353537343132393135353066666538323137386266613038 +63623831623839646133623566303537326566393464323635666435326338643937393161613439 +61653766643064623832313437633566626132623339643832666435353761616562333831386638 +35326631343165313432353536386434643138666638336235313365303966333237343636303961 +34373935383135353434353333643837636437646539306135376538386562323235353130626433 +39306664656631356334353936333765393839623866646361613537323163343232346133626562 +39633230383965393130396637363039393431306537396436366530386338666632396536383263 +39323865613564643139666461313631303564353736323534383533383136633138313662656234 +34363364356638363331343066323564333863316665353039663631636564336535376333666534 +66633766353062626330626561373038333165376162336539343536623330646461633565363732 +33633839633635623965303734666632303231363530363339323232656537373837383939356162 +66626164666234623236646633623436393166313032363339343764333630383264333463653661 +34393635383832613131383366323734373361373866383131633465663034353032363932356531 +38343030646531663835313166346161363639613061316439613639306161343837626534373164 +31363065633832646439666436373862653431363131643934396638303238356563623233663733 +35656638376265316430616266343537616232353331333461646363373062303238303736356266 +66393862343466323534613464386435333435343664373738366465343637333335646564393661 +32383461343263323837356132383933373861656233623765353536336230366639366262353639 +62353430376336333663316365323961326637306363323037623764613661313963366139663930 +39343438376361663930316664653835336130643165623530333862363364623137663461383734 +32353531643036626138313661653332356536303638306165626331616632376662383333343963 +65633964666562383235376231373231663534656265326531396339336234386431356266636538 +37613361663131306163383264643938326139316164303334383237383436633135643162373732 +37386434383061393039376435393761386139623235643333363166333966396233616435343932 +32623730326633303565303537376639336430663363306661353539616661323963643534353434 +37323365613761343434333134306633396264333535643566343061366633393764663164646236 +39393264366266383031663831363662663765643134636532363335623830393732656464653332 +36663038313239366465633336663462356361663032653537393333316261633933666163363165 +39323736666633366265643733366532643561353433363162643563396135353437333361346639 +64353539666536363761323661653762613039333035663336656661356132623136613233323862 +33323065613434336333623865636162666166626435383863373765326631666536646466346333 +64326434336633316334363330626130363836316164313334396631386535363466373632346332 +31626432363663663461653335333038313633633463356332306436373731646336356162303363 +33663762336632373664343364326331633433363530356461353766663265333265393464303463 +62383232336264303439323437306234656136646535616335653233306663303638306132623437 +39386439653065643637663465376464343061653032643530643031313131653866396539313032 +62663639623337633662623836346564366465306337663166313935313736636234666361623939 +63363364643235653163383831356333623935356139613838363232363939346133316433623361 +64643830306363393938326366326637386538326330663433643266376163376565613936323238 +36336264633866663061333037616137393663386166656230623331363436383035303363663636 +61363030313064636562373238386363643130623764333930333062663064376264343165313233 +64666631613965366334646232386339386439643666366633326230366466376335313461666262 +35343463366663393364313765666135636366336163313762623763306563616438303766383662 +66613138613962316430643839333762363235656633363131633331643330393433666130326335 +64373530323263306539306137343238303739383731353937346163333066386663333734623563 +33623365366366326464633730613033343262393633353064323036313630383737613739343437 +65313964343063653365303763613336656536373063666334393530393166393964656134613964 +65343430663735643565306335393963613539666364363462383362663837303030346262666136 +62313861336565393638646463656163613038373039356437646435343765666464373263353238 +39323930613331633261323664353762303736653738306635643565656636303636373031363265 +31343564313566633933343635313163626562386437313434316665346361623836323731666634 +65623933313133316639616165613066343939346631363735383562656263643564613739353366 +62616661326263386165626639376232633061646635396363336135366435383330653936316239 +36366666303531636238613766633930333864616432356637633037323738346531366638613436 +66313964363065633362363462343338363031343730376439316334303339383230366531363432 +63383030616130363830633132363633653232343561323739646366636265386131303636346461 +62343963656533353238653561633539663038393435333539636666363836653833656465316566 +33643364323164313330626136343063613830636234323764336436643839396635303466366537 +35643761336633653031353332613261306136343139643334323739646337656364326265383331 +30393538306632633862666431306133346637366537376439633538653332613064353830323262 +64623335393161363861363132346236636534643763333164333766363839623931343637313733 +36316166366430396232613736353764666231313135313836386337306530343035366635666437 +31343331323637663761626330663964353234613030333333383463663862376538623962313864 +62633361303039303836303630356232636530333731316362316564396363313834333534623363 +35393161326230373635373465643562653663626637336230343330623536313565333466663732 +30343830393965613662663464353035336565306466333165626166346164636331363538623137 +66333230663530633364373138353830326135633935316136353465653661366637333565373137 +36626433333061656236363439306239393137363466386438636238363064313436636530373031 +32663135623266353537626338643835613062383762333832363364663664386133633463613765 +39656232366463653163643432623365333339666161353130653666623036623636666466663432 +38393937303561396530306432626239316464313536316165643965393866626162623331393232 +32396164373331323733626563376164383162343865386432393732343836386435333835336638 +36393933383762643635373333616663643734623032633861306336336434663731646634336364 +64323936383962663965613565353831386666316430613933623664653035303332306433626533 +38646638366461613664646335633339663939366133323337323765653731613763656364383666 +30373561643935613265343431623732393933613133386362623431653938326164363335393365 +31333364316431363036653834393236663964306438376234383435623864333730643838386338 +65333837353134383233343165653165643733623364633536363563363463303831643738363461 +62383738366437646665633036663564326337356435313661396565343639343336633230333662 +36613363396465353931336436303931333431383233613335306134383534313936613039396335 +33323436653930316432366233383439336234653437666564643864663765383732383038663532 +34616566636632626330643930303130636435643730386433663264383931663061393165616539 +38383234636332613130323635353766306534363633613331396431613739376433626237343934 +33383962643938636135626665633965663736653661306264623762646564383735373861376538 +31393236643261636464393831613231616136306633653732323262653736643333393433366638 +39303537313433656632346162366134393464663530333436386534343466393239613038316437 +36643133633966613433386235333932653662386266643032366665356335613065393234323861 +61303731373363643138333136366366666231383565376262316137313966376361666563333664 +65653833353235356431616261326235393339353161303731643864313031366664306131356463 +33653261643232373565626537616635343163343632343138303138636330336232303531663637 +66643532373261343137393861383235623465643662326336663731356563346166333239343039 +30363462306562646335306535633938643730323238313038313939396637616230663866306134 +64613839383137343337653638316532613439393465666466633066323834343737363537653263 +36656135646532623666396430656539663530383034363563363535663537646535353264333161 +38613861356234316563373335346161323162623465376530383661613131333635373736333136 +34623130376166393362353033663266383761393664316463646533656634356234353931323963 +31373366666531316361303233383631383431373431303336363034633231383564373265623364 +35326231363165633639643366326134626332616163666134376666643830636638623139626338 +63656532356661663138633333623231373230663233363264363462623831666331633731396161 +66383035613061383161643735656332633136323333653537356237666563613662303964616166 +31323866353538323737346166396136343436323861636263653661313266386630633563336131 +34393134303964333065643766306533396161333138633463376539656262666462313438666633 +30623138363562343637616433656535633436616664346562343962663065386566333834353938 +62323531663062376633396466613063346431643431353038376665303061313436623832393632 +33653939663961656162323934356233353332316236333235366161333133666631376537316661 +37303536336132303535626133363864323635633330633632646438303639666363333835643464 +66386539663737666565303139643537316236306637346631386134353231356230353735323565 +30303639333634613530613965616263363662356438653333316462613863666130646361666533 +62323435616430356166336661666636306264306334633766663032306134396538376230613539 +33323334633932343965366464353362363432663438653062626463363139663961366134366135 +31326436316261383361633931376137373764336531633938613834396664316331323161333031 +63613534373630363561313965373065373833343033353335356634623961313336643537393061 +32333965396433343137363162316530626338616235376364656230633566383234