1
0

Networks: create internal docker network for proxy server

Prepare to use caddy in docker
This commit is contained in:
Anton Vakhrushev 2025-05-06 11:11:48 +03:00
parent 527067146f
commit adde4e32c1
Signed by: av
GPG Key ID: F5BF52FC352E255A
15 changed files with 207 additions and 184 deletions

View File

@ -12,6 +12,8 @@ services:
- {{ backups_dir }}:/backups - {{ backups_dir }}:/backups
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
networks:
- "{{ web_proxy_network }}"
environment: environment:
- "USER_UID=${USER_UID}" - "USER_UID=${USER_UID}"
- "USER_GID=${USER_GID}" - "USER_GID=${USER_GID}"
@ -25,3 +27,7 @@ services:
- "GITEA__mailer__USER={{ postbox_user }}" - "GITEA__mailer__USER={{ postbox_user }}"
- "GITEA__mailer__PASSWD={{ postbox_pass }}" - "GITEA__mailer__PASSWD={{ postbox_pass }}"
- "GITEA__mailer__FROM=gitea@vakhrushev.me" - "GITEA__mailer__FROM=gitea@vakhrushev.me"
networks:
{{ web_proxy_network }}:
external: true

View File

@ -10,27 +10,9 @@ services:
restart: unless-stopped restart: unless-stopped
ports: ports:
- "127.0.0.1:{{ gramps_port }}:5000" # host:docker - "127.0.0.1:{{ gramps_port }}:5000" # host:docker
environment: networks:
GRAMPSWEB_TREE: "Gramps" # will create a new tree if not exists - "gramps_network"
GRAMPSWEB_SECRET_KEY: "{{ gramps_secret_key }}" - "{{ web_proxy_network }}"
GRAMPSWEB_BASE_URL: "https://gramps.vakhrushev.me"
GRAMPSWEB_REGISTRATION_DISABLED: "true"
GRAMPSWEB_CELERY_CONFIG__broker_url: "redis://gramps_redis:6379/0"
GRAMPSWEB_CELERY_CONFIG__result_backend: "redis://gramps_redis:6379/0"
GRAMPSWEB_RATELIMIT_STORAGE_URI: "redis://gramps_redis:6379/1"
GRAMPSWEB_EMAIL_HOST: "{{ postbox_host }}"
GRAMPSWEB_EMAIL_PORT: "{{ postbox_port }}"
GRAMPSWEB_EMAIL_HOST_USER: "{{ postbox_user }}"
GRAMPSWEB_EMAIL_HOST_PASSWORD: "{{ postbox_pass }}"
GRAMPSWEB_EMAIL_USE_TLS: "false"
GRAMPSWEB_DEFAULT_FROM_EMAIL: "gramps@vakhrushev.me"
GUNICORN_NUM_WORKERS: 2
# media storage at s3
GRAMPSWEB_MEDIA_BASE_DIR: "s3://av-gramps-media-storage"
AWS_ENDPOINT_URL: "{{ gramps_s3_endpoint }}"
AWS_ACCESS_KEY_ID: "{{ gramps_s3_access_key_id }}"
AWS_SECRET_ACCESS_KEY: "{{ gramps_s3_secret_access_key }}"
AWS_DEFAULT_REGION: "{{ gramps_s3_region }}"
volumes: volumes:
- "{{ (data_dir, 'gramps_db') | path_join }}:/root/.gramps/grampsdb" # persist Gramps database - "{{ (data_dir, 'gramps_db') | path_join }}:/root/.gramps/grampsdb" # persist Gramps database
- "{{ (data_dir, 'gramps_users') | path_join }}:/app/users" # persist user database - "{{ (data_dir, 'gramps_users') | path_join }}:/app/users" # persist user database
@ -39,6 +21,30 @@ services:
- "{{ (data_dir, 'gramps_cache') | path_join }}:/app/cache" # persist export and report caches - "{{ (data_dir, 'gramps_cache') | path_join }}:/app/cache" # persist export and report caches
- "{{ (data_dir, 'gramps_secret') | path_join }}:/app/secret" # persist flask secret - "{{ (data_dir, 'gramps_secret') | path_join }}:/app/secret" # persist flask secret
- "{{ (data_dir, 'gramps_media') | path_join }}:/app/media" # persist media files - "{{ (data_dir, 'gramps_media') | path_join }}:/app/media" # persist media files
environment:
GRAMPSWEB_TREE: "Gramps" # will create a new tree if not exists
GRAMPSWEB_SECRET_KEY: "{{ gramps_secret_key }}"
GRAMPSWEB_BASE_URL: "https://gramps.vakhrushev.me"
GRAMPSWEB_REGISTRATION_DISABLED: "true"
GRAMPSWEB_CELERY_CONFIG__broker_url: "redis://gramps_redis:6379/0"
GRAMPSWEB_CELERY_CONFIG__result_backend: "redis://gramps_redis:6379/0"
GRAMPSWEB_RATELIMIT_STORAGE_URI: "redis://gramps_redis:6379/1"
GUNICORN_NUM_WORKERS: 2
# Email options
GRAMPSWEB_EMAIL_HOST: "{{ postbox_host }}"
GRAMPSWEB_EMAIL_PORT: "{{ postbox_port }}"
GRAMPSWEB_EMAIL_HOST_USER: "{{ postbox_user }}"
GRAMPSWEB_EMAIL_HOST_PASSWORD: "{{ postbox_pass }}"
GRAMPSWEB_EMAIL_USE_TLS: "false"
GRAMPSWEB_DEFAULT_FROM_EMAIL: "gramps@vakhrushev.me"
# media storage at s3
GRAMPSWEB_MEDIA_BASE_DIR: "s3://av-gramps-media-storage"
AWS_ENDPOINT_URL: "{{ gramps_s3_endpoint }}"
AWS_ACCESS_KEY_ID: "{{ gramps_s3_access_key_id }}"
AWS_SECRET_ACCESS_KEY: "{{ gramps_s3_secret_access_key }}"
AWS_DEFAULT_REGION: "{{ gramps_s3_region }}"
gramps_celery: gramps_celery:
<<: *gramps_app # YAML merge key copying the entire grampsweb service config <<: *gramps_app # YAML merge key copying the entire grampsweb service config
@ -47,9 +53,19 @@ services:
- gramps_redis - gramps_redis
restart: unless-stopped restart: unless-stopped
ports: [] ports: []
networks:
- "gramps_network"
command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2 command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2
gramps_redis: gramps_redis:
image: valkey/valkey:8.1.1-alpine image: valkey/valkey:8.1.1-alpine
container_name: gramps_redis container_name: gramps_redis
restart: unless-stopped restart: unless-stopped
networks:
- "gramps_network"
networks:
gramps_network:
driver: bridge
{{ web_proxy_network }}:
external: true

View File

@ -5,3 +5,10 @@ services:
restart: unless-stopped restart: unless-stopped
ports: ports:
- "127.0.0.1:{{ homepage_port }}:80" - "127.0.0.1:{{ homepage_port }}:80"
networks:
- "{{ web_proxy_network }}"
networks:
{{ web_proxy_network }}:
external: true

View File

@ -12,12 +12,18 @@ services:
container_name: keycloak_app container_name: keycloak_app
command: ["start-dev"] command: ["start-dev"]
restart: unless-stopped restart: unless-stopped
ports:
- "127.0.0.1:{{ keycloak_port }}:8080"
networks:
- "{{ web_proxy_network }}"
volumes:
- "./data:/opt/keycloak/data"
environment: environment:
KEYCLOAK_ADMIN: "{{ keycloak_admin_login }}" KEYCLOAK_ADMIN: "{{ keycloak_admin_login }}"
KEYCLOAK_ADMIN_PASSWORD: "{{ keycloak_admin_password }}" KEYCLOAK_ADMIN_PASSWORD: "{{ keycloak_admin_password }}"
KC_HOSTNAME_URL: "https://kk.vakhrushev.me" KC_HOSTNAME_URL: "https://kk.vakhrushev.me"
KC_HOSTNAME_ADMIN_URL: "https://kk.vakhrushev.me" KC_HOSTNAME_ADMIN_URL: "https://kk.vakhrushev.me"
ports:
- "127.0.0.1:{{ keycloak_port }}:8080" networks:
volumes: {{ web_proxy_network }}:
- "./data:/opt/keycloak/data" external: true

View File

@ -6,11 +6,14 @@ services:
image: outlinewiki/outline:0.83.0 image: outlinewiki/outline:0.83.0
container_name: outline_app container_name: outline_app
restart: unless-stopped restart: unless-stopped
ports:
- "127.0.0.1:{{ outline_port }}:3000"
depends_on: depends_on:
- outline_postgres - outline_postgres
- outline_redis - outline_redis
ports:
- "127.0.0.1:{{ outline_port }}:3000"
networks:
- "outline_network"
- "{{ web_proxy_network }}"
environment: environment:
NODE_ENV: 'production' NODE_ENV: 'production'
URL: 'https://outline.vakhrushev.me' URL: 'https://outline.vakhrushev.me'
@ -52,6 +55,9 @@ services:
image: valkey/valkey:8.1.1-alpine image: valkey/valkey:8.1.1-alpine
container_name: outline_redis container_name: outline_redis
restart: unless-stopped restart: unless-stopped
networks:
- "outline_network"
outline_postgres: outline_postgres:
image: postgres:16.3-bookworm image: postgres:16.3-bookworm
@ -59,7 +65,15 @@ services:
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- {{ postgres_data_dir }}:/var/lib/postgresql/data - {{ postgres_data_dir }}:/var/lib/postgresql/data
networks:
- "outline_network"
environment: environment:
POSTGRES_USER: '{{ outline_postgres_user }}' POSTGRES_USER: '{{ outline_postgres_user }}'
POSTGRES_PASSWORD: '{{ outline_postgres_password }}' POSTGRES_PASSWORD: '{{ outline_postgres_password }}'
POSTGRES_DB: '{{ outline_postgres_database }}' POSTGRES_DB: '{{ outline_postgres_database }}'
networks:
outline_network:
driver: bridge
{{ web_proxy_network }}:
external: true

View File

@ -26,3 +26,8 @@
- name: "Login to yandex docker registry." - name: "Login to yandex docker registry."
ansible.builtin.script: ansible.builtin.script:
cmd: "files/yandex-docker-registry-auth.sh" cmd: "files/yandex-docker-registry-auth.sh"
- name: Create a network for web proxy
community.docker.docker_network:
name: "{{ web_proxy_network }}"
driver: "bridge"

View File

@ -23,13 +23,6 @@
- "docker" - "docker"
owner_ssh_keys: owner_ssh_keys:
- "{{ lookup('file', 'files/av_id_rsa.pub') }}" - "{{ lookup('file', 'files/av_id_rsa.pub') }}"
owner_env:
PROJECT_NAME: "{{ app_name }}"
DOCKER_PREFIX: "{{ app_name }}"
IMAGE_PREFIX: "{{ app_name }}"
CONTAINER_PREFIX: "{{ app_name }}"
USER_UID: "{{ user_create_result.uid }}"
USER_GID: "{{ user_create_result.group }}"
- name: "Create internal application directories" - name: "Create internal application directories"
ansible.builtin.file: ansible.builtin.file:

View File

@ -24,13 +24,6 @@
- "docker" - "docker"
owner_ssh_keys: owner_ssh_keys:
- "{{ lookup('file', 'files/av_id_rsa.pub') }}" - "{{ lookup('file', 'files/av_id_rsa.pub') }}"
owner_env:
PROJECT_NAME: "{{ app_name }}"
DOCKER_PREFIX: "{{ app_name }}"
IMAGE_PREFIX: "{{ app_name }}"
CONTAINER_PREFIX: "{{ app_name }}"
USER_UID: "{{ user_create_result.uid }}"
USER_GID: "{{ user_create_result.group }}"
- name: "Create application internal directories" - name: "Create application internal directories"
ansible.builtin.file: ansible.builtin.file:

View File

@ -18,13 +18,6 @@
- "docker" - "docker"
owner_ssh_keys: owner_ssh_keys:
- "{{ lookup('file', 'files/av_id_rsa.pub') }}" - "{{ lookup('file', 'files/av_id_rsa.pub') }}"
owner_env:
PROJECT_NAME: "{{ app_name }}"
DOCKER_PREFIX: "{{ app_name }}"
IMAGE_PREFIX: "{{ app_name }}"
CONTAINER_PREFIX: "{{ app_name }}"
USER_UID: "{{ user_create_result.uid }}"
USER_GID: "{{ user_create_result.group }}"
- name: "Login to yandex docker registry." - name: "Login to yandex docker registry."
ansible.builtin.script: ansible.builtin.script:

View File

@ -9,7 +9,7 @@
vars: vars:
app_name: "keycloak" app_name: "keycloak"
app_user: "{{ app_name }}" app_user: "{{ app_name }}"
base_dir: "/home/{{ app_name }}" base_dir: "/home/{{ app_user }}"
tasks: tasks:
- name: "Create user and environment" - name: "Create user and environment"
@ -21,13 +21,6 @@
- "docker" - "docker"
owner_ssh_keys: owner_ssh_keys:
- "{{ lookup('file', 'files/av_id_rsa.pub') }}" - "{{ lookup('file', 'files/av_id_rsa.pub') }}"
owner_env:
PROJECT_NAME: "{{ app_name }}"
DOCKER_PREFIX: "{{ app_name }}"
IMAGE_PREFIX: "{{ app_name }}"
CONTAINER_PREFIX: "{{ app_name }}"
USER_UID: "{{ user_create_result.uid }}"
USER_GID: "{{ user_create_result.group }}"
- name: "Create application data directory" - name: "Create application data directory"
ansible.builtin.file: ansible.builtin.file:

View File

@ -29,6 +29,8 @@
restart_policy: "unless-stopped" restart_policy: "unless-stopped"
published_ports: published_ports:
- "127.0.0.1:{{ netdata_exposed_port }}:19999" - "127.0.0.1:{{ netdata_exposed_port }}:19999"
networks:
- name: "{{ web_proxy_network }}"
volumes: volumes:
- "/:/host/root:ro,rslave" - "/:/host/root:ro,rslave"
- "/etc/group:/host/etc/group:ro" - "/etc/group:/host/etc/group:ro"

View File

@ -9,7 +9,7 @@
vars: vars:
app_name: "outline" app_name: "outline"
app_user: "{{ app_name }}" app_user: "{{ app_name }}"
base_dir: "/home/{{ app_name }}" base_dir: "/home/{{ app_user }}"
data_dir: "{{ (base_dir, 'data') | path_join }}" data_dir: "{{ (base_dir, 'data') | path_join }}"
postgres_data_dir: "{{ (base_dir, 'data', 'postgres') | path_join }}" postgres_data_dir: "{{ (base_dir, 'data', 'postgres') | path_join }}"
postgres_backups_dir: "{{ (base_dir, 'backups', 'postgres') | path_join }}" postgres_backups_dir: "{{ (base_dir, 'backups', 'postgres') | path_join }}"
@ -24,13 +24,6 @@
- "docker" - "docker"
owner_ssh_keys: owner_ssh_keys:
- "{{ lookup('file', 'files/av_id_rsa.pub') }}" - "{{ lookup('file', 'files/av_id_rsa.pub') }}"
owner_env:
PROJECT_NAME: "{{ app_name }}"
DOCKER_PREFIX: "{{ app_name }}"
IMAGE_PREFIX: "{{ app_name }}"
CONTAINER_PREFIX: "{{ app_name }}"
USER_UID: "{{ user_create_result.uid }}"
USER_GID: "{{ user_create_result.group }}"
- name: "Create internal directories" - name: "Create internal directories"
ansible.builtin.file: ansible.builtin.file:

View File

@ -27,8 +27,7 @@
- name: "Prepare env variables." - name: "Prepare env variables."
ansible.builtin.set_fact: ansible.builtin.set_fact:
env_dict: '{{ owner_env | combine({"CURRENT_UID": user_create_result.uid | default(owner_name), "CURRENT_GID": user_create_result.group | default(owner_group)}) env_dict: '{{ owner_env | combine({"USER_UID": user_create_result.uid, "USER_GID": user_create_result.group}) }}'
}}'
- name: 'Set up environment variables for user "{{ owner_name }}".' - name: 'Set up environment variables for user "{{ owner_name }}".'
ansible.builtin.template: ansible.builtin.template:

View File

@ -1,6 +1,6 @@
app_name: "homepage" app_name: "homepage"
app_user: "{{ app_name }}" app_user: "{{ app_name }}"
base_dir: "/home/{{ app_name }}" base_dir: "/home/{{ app_user }}"
docker_registry_prefix: "cr.yandex/crplfk0168i4o8kd7ade" docker_registry_prefix: "cr.yandex/crplfk0168i4o8kd7ade"
homepage_web_image: "{{ homepage_web_image | default(omit) }}" homepage_web_image: "{{ homepage_web_image | default(omit) }}"

View File

@ -1,118 +1,121 @@
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
61653632623534313563323536353134663639383236653566313666613431353539333931626631 63336665643133366538363963613966643631396163333335386462303362346632336332663763
3264323462653132646562343266356261353864663232350a383964366432323263303963363334 6561306531386234636433663866373239396533363361610a373331666131393038346230666434
30663863646436393661653738656361393761373839353462313239313564626436323434373830 31323362623166643732326431343766666663623431663964653335393863306264643136383935
3931646664373465320a323563623761386232306162643039613730336130393531373437633530 6230663135383161660a336461353136383735393631383333616665303836333561306663366434
33343662636535373533643265366364626663666136633730333836313337333631333061353535 30313738316131306564626330623164323766666530346632613932343233316162313033323130
36363666623831366464333630366330323864656434633439353132633530663365386561616432 37373330346539356534663837356131313631643665373432316434616431366438303461336566
61303462333836356133633866313666663733613032666331616635376562343131356564666337 62386463353936383762353331646637393537666164346364643036323166663963653864633763
36646235623638303732346330373961336334646436633034653238323764373262313962343233 35353230656333376465666531306333356533343836653933366230393466633638353865633762
63376338636666633436356166363463623832643435346334633465336432383134336432346633 64663531613939663439396634343033303337363630383532333633393937396336363261313963
37663332323432663130306230666534323239646234363832306538306336656335663561613065 61646163643339363831366633383134346536343332393366646237626335303130396435396166
65633635626532333438633466353030643839663666633365663738633137393834316233323436 38613639373037326430363337623036613135346139633061386236363131646566616433346535
64333365663237373464393238323430316261366636333531653036383331656333373037323433 62386633396232666538393066363139336233313161636365373632363161656132636238613162
38303961343836313532373466613232383030663430343031386334386263326163663532373264 31326566616438393834336331383432373962343436626464363266636535626264353466623631
64396132613834663332616533346236623938353531613263666138306665376232666535376264 39303164396261373739333137646266323939306133386366383233666235303636343337396261
63663934333461623332333964346435316465636366663634306165666361386332346338633638 39623836383232303737363032613361323437336364346430333931373030643635663730383332
34316136633131356336613031306130363332633132316361633433323837313238623435376563 62623864623238373861656664393061316433393832646431333636633662313037616665666536
62666636643235353966386237393334326261623233303935623136643439623365333930326661 36396538346632393563386662393166626230623430626530643766643638663332613436323534
65303239363232636432623162626138313466323661636438393430306163356264656263333865 34653336623539626632396364653337313430356338363131343363346530626133333938353834
64386231646364626564326466653831623563633036353161643731343133643933383632653162 30336535333933333764346437376261343434383237336331653938613766386234656266366465
30336537366332313239396363633333386136396530613366343965663133396138316534336431 33323531623838303862396462373835323366613866306234373737393263373438373635653861
35663038343533653065353639633065393636326662353235376666613630383338393337383634 31343235323162393461666335386136386435646466383631623237633734336161303165633366
32623864323964383837333434343233326338353630356137303665653864346261336238653664 34656631333038323039393338376232663930656164626334393139313531373437306534353133
31356334383535386562336131626431373533373038376238333830333136326337656234393565 33636436666530616535326631363537323131313132623830316139346637386566316138383833
62363335346630346666383138333939326562303433396663663466326362633965323238656334 36323633636366353932386235303239623333396636333834313833353232373461323231393066
61333335323664646166356665333639326437333539316466656533613365663165323138396237 61323339623865306264353937373163383435623962383364343163306432353834613536636665
61386366336530626665363765373538356136393536353831623730313065346238393765313435 36343837323937653533633364623435663038333038353663666566383336366366383132363164
34623634376133336534303461666561353864336130633435316566366434643435336231386265 31353338613466343834313635373131626338313230653733666633646162316366343630613630
64353365393830373331653739663561336565643435656634643632336566393165623462383433 64336539373231306336643437646161353230633763366230346338353264353561376333623132
64633065663065353561393365333137383465376365393639306561633561306335343132353636 30363764656662396230343531306462343139333336343135613063386530343265663537383539
36366362353739613662383463373232663735333230613137396338373530373939386131663437 61353137373235663038323166613564386631623230356263316463653764656464393866646536
66643634663761373431353339356439383035653932373532323765653466313430303637376261 36366162333637633438343038336532346432633632613134646361393936306634353566376363
66333337363538643765613535363038633838323136663666386638363263643930346533663433 64353766613361663434383638613637626333323538303433313235303961376536333338353237
61303231346562313538306461353763383861393835633731303539373964653661623362376363 32346662313530356564653463376562366239626465646230636531356235396537663261663535
65396439336632353534326561393666396337376235373238613866626466666561656665323066 34623638643565373164363339646464303864373437333232616339393465396133653262376636
38376337646430616231383933666532633536623232643166376336373331353233363738613037 62633136356636623663633562623462303362353139373630313064663738363139636336316438
30393831316537343265393666383863323830303662326162336631346161306663646535343337 66373665666661376131366432376437323439373863376136336565636337356166396561363662
65326330353831393139616566303432626634376234336661333966653835373437383233383537 32646438346561623132633238636131373561336335336161366261393634323139363062663439
32333163393532643633646435663962613335623631366165653664653632303632623462313664 37666664363461353131613637646434343361336236383433666230333964396531356362623862
36306132646265623438323237326633353463326433366430653766373836333130353833633863 32636530306534386266643033316262333637653933373133363935646561663064306266323531
31616132393462386562623565353730333435303930323034353530353734313033356439623463 38333936666266343133666563653363373635663465386235393463623361316663613136376134
66666436373434313437623064356133313632623932306630663136393336363431633162393764 62643539633438636263313633343562613664626432623731393061333261363937613563343131
34383863653437353438306362353062303463303938366133333135366464653164316465646264 30623137313063633636613733633237346464373234656333346336643532383931333938633433
65383536333064663866373233663265376536613462663637363965623834626362643439636463 36363536323264346537653761653033633133626265613831306262343062613130643561363563
31633939653635366235323261666636623662303163623632356265626530303938306239666462 37633664663039666663666362346636353139393265343165363466616338643666336534613033
62363237363836383130323364373765396531356232373133616464373434343166313065633538 65343164316235356439366335316263383166326165326134653963656438343630643037353035
31353036396231643963623530303938666434653239656338363633663835653236626537333366 63366532373464366662636330326334333732646336613730333537336335623265626537633634
32653631383938373163653830616238623363643537363139366465633935313464333463633165 34623366656337623635653131383936643436653735636165643330393034383437616162346632
30373039396366623135346235656563623564393131353361323038346364323232633331363666 39663235663362346563306130343266303834663433336364653563353466383535383532366539
66373330666135323532333537613263303765626532343034626637323663613863636362623930 64356536613539636630373039663035316335313335353137366537333838363135653236393331
66326133373838626261323161313238396433643638623964376430666332336363393930383935 37633065323762613330616535363430653865366666623730663230333436323839626131643331
39386432376361333935343736626166623761373262343561636661393135326566303866616335 31353662383332333638666336656466646530376339373435633037323432333538656433623865
39333732333335646237616661396638336263623065393737323032626133333735613763366537 63616531346265353238373531363232326331616265343233393161383064393866633536343437
30313930376463393566633965323630333038323433383433316262383561313835663733306166 36636336633934633236393034346138376466613839653938353336343163313830303330633565
37303436383639326237313030333931646135636433636363346535306336393237636335346632 30373833323435306138343933333837636161393862306430613161396233323661333430626364
39373064366434653438663234346430333738613865353937326464343031353866383536336436 65356662336636653039626363623135386336626566613837613261336138623663316266316565
65326230623435633432316535393835336164623966366236623636643038646263373964316338 32323865663662376335626432333934356239363563623965353436356536323339656461616233
39633833616233613630353230623463343936376539343961383738303463393866316363656632 61653930666266363165303461643465333063366166346636303163333738663165353139626430
31343866313961633531663739323264643436663936643531306330623630353231393337666535 63356466616635656565383938313730366635316533656261376436396463343434626564643963
39303462323439333166303239343931373363303161626132623933613163383536363233623865 32663961623063343233323037366631356662343963313034626633326564633066326633353133
30616639316661313461633738323834653032633036373039636334383533613038326238323337 34663737356237306363356237383461376534356235316433326535616465633936363238383232
35623736303332373433323334616263353233613365633936653864396565343731353535663233 61616666656261336434356262663066316630613633373535656465353262633934353938643664
37363265383864393366363864626238303634626232306632303464613164363463643666636438 32303234363461633438383037386364366134303933623332356165613335626266633132633932
39656637373337313338303837326435353039373162623536383232303134303833383235663262 64333366353837353461353261356434356361303665346631636632653965336162373536393935
32393034626136316131633234326435356630323263393034623537653330356162643037323764 39663531613233393364353631383033303132323962356462366561343333663335383831353736
38336562623262346334623263336465356262303830643331366566306531666139326530303762 36306534653030666265343462653730306438343733633066353965393462353136656336333036
33316361336132303764353834663863313035333363313663643363383730646562653562383336 64313733376565633264613133336162366130363633313336343131353362363638666634393330
32333734323139636531656433653365333937616532343662383262363331336332376464656134 66613961616238373566386362316430353966333136626663653537653838346533353862303437
35353362653134343539336438366465663166343638386237386663323439643366373364323030 33396630303764386534666666373737636666383361383765396466623639353265653831383761
63633638623064323566303734326638626632656663333135656636386163666438646139623330 65363637386539643439343434383534646563343038626536653836346437323666333362623838
32373333653965303632373664396238313238373564613335616435636139653331396235653638 39366332613631363363633064646134366639386164313636343130613461306237646564623061
64646166383039393166613331363936306337313839643162363033643536343565326231336666 66363261303737633434383161326530646365366539623966396166626533636538633037396239
31353261626566366336393033373366316231633763373733356565346536343066333034313036 30376639353566313637656362353862303937356431653733346363306138333162326166633236
37613436316532656665313965643634616531663438623866386538646562343832626465393064 38336539333462383838653937343466376365393962303037306536633231343133313738343736
35613135643334613866343462336532303866343738623637626630666264393736336433633366 65626264333265656535343339643361366261323066376436346331383365383135626262393139
65613531366332633565333664616538663061623962313965356666663839623139663238613364 62316233303366303932343036316238643135616335393431323030396263653031663732306231
34373363363366323230626165623465366534303437313030366166623033666661393661373937 39346131373963626433316363393830343330353433623136613532363833366633326262313636
66383436376262393139323062363535313166393134376433323166333864343635353165613432 30323365343364336662643235386464373432343030333836326465663966336563366461626534
33636330643633373966323163646437613334366135323430616662616365366430313830363736 61323163663330623766656439623837303263643038313566663139363036373666333732303237
64633535366465303131323738306434386137323466626463323237626638363464303230653465 37626330663664636236613038373937306563343635343034663832313363613161303630323934
66656634306138663064373331386339363734383563326566373931316564323263353161366130 66393966366537393466383764386434666132393038376663623333613061633465306235316130
32666631313661363938323964333064323538336234306637323164643139636564396332366136 37393133303062346334386634333539356435643163336332386238643362373736376164323630
35336635383533353330316565393166663435613062643839353464623434346635373838646164 64313661303738366565376564656665316166326532633036643533306135336564326334393436
34363264383265306337646336653637326362396566303339343933646534373066636363333866 32656431383534383865333737376531306665376635616635623766396165613035393330336239
30633832373138386566353661636239386136366464346565613263653236393038363263376561 30643230323737373262313363316238316533653265646661313736323835393362643961633030
64343635656437326162303436636633353566323632613234306364643863626532616566306363 63646664303639316632383763323537363264663739633530346538643663373130353962323436
61393036353137626361633238386664353061396564333032356161643033636338353336623063 66306561376638373436366233336535313761623532633862303533663762623838326239376664
65613731353264626563633361383334373633646436643039663335616466323737663536653539 62663534363262346232666463373332646234623733346165613630643330356131616632353533
64333330383830636363663731613734373466363337386537333465323163656465623337303537 66353434326233643561363730373964393039343766393862663563643939343831653666643564
63366462303039613161363162636435363232333235363136646363663733653937346563316261 31626538633130313964636230343530333535353831613566346165303330663964666161666363
66626562623330373737393263343038316466646138633337656461396330626130333265616335 66623736323464663731343431373938323331663364666634646165643030646266363261646130
32303462333231343264613131656134613034333138363036333730323134646461366233393533 63373830316338303564343239343761623231356562316536626135316430386530613238353233
35643435343561343362313338663465653432306136306466616437643734313339306635653063 32646438323637303038653737386363313162343535396632363030386333616561613966363163
62306537313262636239336165393138306232333433373163346265313538623330663166646465 65326461653063323132623130336265303764653965323966663466376463623433623365353137
64353163386432656163623130316463353536613430313634393866383266303534323266386163 62363039616630313034373734633261303830636334333233393562386563363963666263643561
65363730376239303935303433393535386137626136666166353631656661393265646630626362 38363766386465643835383837353631353138313263346361366266666161633334343238396165
37313830393966666637306436303764333733346162393165343831386434373832633165313831 65646139626537643261656564333131643566306636316137333636303430613535353831343436
39313861396238626538663633363139646638346137363439643065656334653365346533303535 31373734333231393737643432353361623061613363383433366366313230366461663031303864
62373136363631326534313736666539323336396565633935613434373436353332396662323263 65616337396161373733386463303730396437333330366563346437333331343435313134376536
64383031663937656563393336323462353962326638383762616163363963303966333265356538 33313861376333386138336339313935623861653435323039323835633038653263656364656239
36373865663561333430383333323332623961396432326131376331663536663761633934653630 39383561643834313635663464636261643962373434383733653631336265386638383430653533
31653539343933393663376563643139663732366431373536613461646133623037363336363736 38613838316563393631366263306138353161616635386332656331343935336538626331386634
63356638306235313932346365303439313136336235613633636363303962373236613339356238 37636133353637363932346462336539623366613066313336643739653661336336393131383665
37623432353662373534313266346461623338626135316537646339343962313335306534663966 39613162613863643761623737326438313732363263666135623537636266363664316430393366
30363235636237323834386332656139633765623930646631636162353662323332303935636332 34663161366337386436353333393637383231333564633932333238643362396232353430353136
35366631363035383065663337386239316235653237333431313665646333356530643637326464 34343562366363613664646465313135316438386532653539656137366436663630623831323466
65616262326136376233383334393065623562326638613466653634363735336363653833376666 32393230333330323761656665363731656462363536396632343934643932373939323834336238
39336231643461623932333631323362393230613164616562343266633064336431366161636639 66666132326334353165366535326130333831353537383931366539616237633830386234626366
36323063313262333235663062393535303261313830363161636661663033616337383764376434 30663162363531613937343135633032316338646433633262643462316631356434363563386339
61333034336431373633383739346639643765373930323162306230353063383730356439663336 39366666303062346663653435313966663930373238613037386430313063386534666562303336
31373137316231316136356137353530646431363437333937633966633837393733333764343334 64393763323336356631376633353037326464383639333734306161623463373466623734306231
63663537326361646165396438393230316461393039613831616534636534353365353838356262 34616564656466336161346664326230633938393834323432303562666437323764336137663966
64353434636466633963323536323038343664333039306432326662363936323761646665363831 66373238386663613631353964353339333738323032376465373736636132323535626164356464
64616661363665393764343262346234623636383330366363366332613662313230646163643430 33366162646563613464383663323965663766376530613562666661643137656137366237303033
61363463306631336632393861333830376539366238343963306131306438623733386665626130 34373733633738323566306261613135393533346332633339396436663438653761363530386639
33376536373364303565633132353565373365643964343737323632396131393865303166366331 63396461623465343862323639396333313639636632306236393438386262393664646564333238
33353538613235343834623865373461613761653536363137346136353663333733616431643937 65653462376138636332653933366162396337343530636338616336333263656266383736386535
38323532663163353734316635623236306331333233393366376563643661653763 63643034393035633533663236366135363466653765383366336430646562313763336561376334
64396430343330653335326133616566663533313233616432666264623231666338393730623531
33376163666430623835376336363863356237336137323066356262333436623266323661613765
61656662373435663132