Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

CORS config for FaaS

Be­cause I want to be able to de­ploy ran­dom python code eas­i­ly to my own server, I have set­up a "Func­tion as a Ser­vice" thing, called faasd (think of it as poor peo­ple's AWS lamb­da). More de­tails on how, why and how it turned out will come in the fu­ture. BUT: this ex­plains how to fix the un­avoid­able headache CORS will give you.

Sit­u­a­tion:

  • The Faasd serv­er runs in some ma­chine, which is prox­­ied by a Ng­inx serv­er avail­able at http­s://­­faas­d.ral­si­­na.me

  • Apps are just HTML pages some­where in­­­side ei­ther http­s://ral­si­­na.me or some oth­­er sim­i­lar do­­main.

What will happen?

You will set­up your func­tion, test it out us­ing curl, be hap­py it work­s, then set it up in your web app and get an er­ror in the con­sole about how CORS is not al­low­ing the re­quest.

What is CORS and why is it annoying me?

CORS is a way for a ser­vice liv­ing in a cer­tain URL to say which oth­er URLs are al­lowed to call it. So, if the app are in, say, http­s://nom­bres.ralsi­na.me and the func­tion lives in http­s://­faas.ralsi­na.me then the ORI­GIN for the app is not the same as the ORI­GIN for the func­tion, so this is a "Cross Ori­gin Re­quest" and you are try­ing to do "Cross Ori­gin Re­source Shar­ing" (CORS) and the brows­er won't let you.

How do I fix it?

There are a num­ber of fix­es you can try, but they all come down to the same two ba­sic ap­proach­es:

Option 1

Make it so the re­quest is not cross-­source. To do that, move the func­tion some­how in­to the same URL as the page, and bob's your un­cle.

So, just change the proxy con­fig so nom­bres.ralsi­na.me/­func­tions is prox­ied to the faasd server's /func­tions and change the page to use a re­quest that is not cross-o­rig­in, and that's fixed.

I don't want to do this be­cause I don't want to have to set­up the proxy dif­fer­ent­ly for each ap­p.

Option 2

Have the func­tion re­turn a head­er that says "Ac­cess-­Con­trol-Al­low-O­rig­in: some­thing". That "some­thing" should be the ori­gin of the re­quest (in our ex­am­ple nom­bres.ralsi­na.me) or "*" to say "I don't care".

So, you may say "Fine, I'll just add that head­er in my re­sponse and it will work!". Oh sweet sum­mer child. That will NOT work (at least not in the case of Faas­d)

Why?

Be­cause web browsers don't just make the re­quest they want and then look at the head­er­s. They do a spe­cial pre­flight re­quest, which is some­thing like "Hey, server, if I were to ask you to give me /func­tion­s/what­ev­er from this orig­in, would you give me a CORS per­mis­sion or not?"

That re­quest is done us­ing the OP­TIONS HTTP method, and Faasd (and, to be hon­est, most web frame­work­s) will not process those by pass­ing them to your code.

So, even if your func­tion says CORS is al­lowed, you still will get CORS er­rors.

You can see this if you ex­am­ine your browser's HTTP traf­fic us­ing the de­vel­op­er tool­s. There will be an OP­TIONS pre­flight re­quest, and that one does­n't have the head­er.

So, the eas­i­est thing is to add those in the proxy.

So, in my case, in the prox­y's ng­inx.­con­f, I had to add this in "the right place":

  add_header 'Access-Control-Allow-Origin' '*';

What is the right place will vary de­pend­ing on how you have con­fig­ured things. But hey, there you go.

En que ando? (19/7/22)

Es­to es una es­pe­cie de se­cue­la a Lo que an­do ha­cien­do de ha­ce un me­s.

Si­go ha­cien­do lo mis­mo? Ma­so. Arran­que­mos con qué pa­só con lo que es­ta­ba ha­cien­do.

Lo que estaba haciendo antes

Compu Artesanal

Hi­ce co­sas, pe­ro de­ci­dí cam­biar la CPU por una Ra­d­xa Ze­ro ... que no an­da con mi mo­ni­to­r, así que me creé un su­bpro­yec­to de "ha­cer que an­de".

Software configurado para pantallas raras/malas

Ter­mi­na­do, por lo me­nos a un ni­vel de co­mo­di­dad su­fi­cien­te. So­lo fal­ta pu­bli­car de al­gu­na ma­ne­ra.

Software que creo que nadie usa, pero debieran!

No vol­ví a usar nin­gu­na de las co­sas que men­cio­né :-D

Sin em­bar­go, acá es­tá el so­ftwa­re que na­die usa pe­ro de­bie­ran, de es­te me­s.

  • dolt una ba­se de da­tos com­pa­ti­ble con MyS­QL pe­ro que vis­ta de otra ma­ne­ra es ... co­mo gi­t?

La per­for­man­ce es me­dio fa­lo­pa pe­ro es muy pio­la pa­ra pu­bli­car da­to­s. Ejem­plo.

  • rq­­li­­te la res­­pues­­ta a "Ne­­ce­­si­­to usar sq­­li­­te pe­­ro no quie­­ro mo­­­ver un ar­­chi­­vo de da­­tos de un la­­do pa­­ra otro"

  • st una te­r­­mi­­nal su­­per li­­via­­na que no es una ba­­zo­­­fia! Ten­­go un fo­­­rk

El Mouse-Joystick

Aban­do­na­do (o ter­mi­na­do, que es lo mis­mo­).

Programar Raspberry Pi Pico

No mu­cho

Lo que estoy haciendo ahora

Nuevo server

Mi­gré mi ser­ver a una Ra­d­xa Ze­ro una com­pu que tie­ne per­for­man­ce ti­po ras­pi 4, pe­ro en un for­ma­to fí­si­co ti­po ras­pi ze­ro.

Al te­ner más ca­pa­ci­dad de cóm­pu­to y me­mo­ria, le me­tí mas ser­vi­cio­s!

Mo­ví to­do http://­nom­bres.­ral­si­na.­me pa­ra que se eje­cu­te ahí. Eso im­pli­ca una ba­se de da­tos (r­q­li­te) y un en­torno de eje­cu­ción es­pe­cia­l, por­que no quie­ro que si de gol­pe la gen­te lo usa me ti­re aba­jo los otros ser­vi­cio­s. Por eso ...

Firecracker + Ignite + Faasd

Quie­ro po­der pu­bli­car bo­lu­de­ces he­chas rá­pi­do en Py­thon (o en otros len­gua­je­s) sin te­ner que pen­sar en có­mo ha­cer el de­plo­y­men­t, o de si a mi ser­ver no le va a dar el cue­ro y me va a ti­rar al­go "im­por­tan­te", o de pro­ble­mas de se­gu­ri­da­d, etc.

En­ton­ce­s:

  • Pa­ra de­plo­year fá­ci­l: faasd
  • Pa­ra ais­lar­lo den­tro del ser­ve­r: ig­ni­te
  • Pa­ra te­ner ba­se de da­tos pa­ra bo­lu­dea­r: rq­li­te

De esa ma­ne­ra tie­ne un to­pe en cuan­to a con­su­mo de re­cur­so­s, y pue­do de­plo­year sim­ple­men­te con un co­man­do.

Impresión y Diseño 3D

Si quie­ro ha­cer una no­te­book, ob­via­men­te eso im­pli­ca di­se­ñar la car­ca­za y un mon­tón de otras co­sas, por lo que he te­ni­do que apren­der so­bre co­mo ha­cer esas co­sas.

He usa­do una va­rie­dad de he­rra­mien­tas y es­toy MUY FE­LIZ con una que se lla­ma Ca­d­Que­ry que per­mi­te crear ob­je­tos es­cri­bien­do Py­tho­n!

He lle­ga­do al mo­men­to en que me sien­to có­mo­do, cuan­do no ten­go el ob­je­to que ne­ce­si­to, o ten­go par­tes y me fal­tan otra­s, sim­ple­men­te de de­cir "o­k, la ha­go yo­".

Datos sobre nombres de Argentina

Ha­ce unos años pu­bli­qué una "a­pp" en http://­nom­bres.­ral­si­na.­me pa­ra ju­gar con la ba­se de da­tos ofi­cial de nom­bres de Ar­gen­ti­na. El RE­NA­PER ha­bía pu­bli­ca­do la lis­ta de nom­bres de pi­la y canti­dad de gen­te con ese nom­bre en ca­da año des­de 1922 has­ta 2015 y da­ba pa­ra ha­cer una co­si­ta di­ver­ti­da cu­yo uso prin­ci­pal ha si­do ha­cer­me el gra­cio­so en twi­tte­r.

Esos da­tos los sa­qué de acá y se usa­ban en es­ta pá­gi­na ... que ya no an­da

Pe­ro ... los da­tos es­tán pu­bli­ca­dos co­mo CS­V, y la ca­li­dad es muy ma­la, y pa­ra po­der usar­los hay que im­por­tar­los en una ba­se, y ha­cer bús­que­das cuan­do la or­to­gra­fía de los nom­bres es va­ria­ble es un lío y ...

Así que de­ci­dí pu­bli­car mi ba­se "lim­pia" en al­gu­na par­te, y ya que es­ta­mos tam­bién una co­pia de los da­tos ori­gi­na­le­s, pe­ro en una ba­se SQL que se pue­da usar di­rec­to.

Bus­can­do co­mo ha­cer­lo en­contré Dol­tHub que es "co­mo Gi­tHub pe­ro pa­ra da­to­s" así que de­ci­dí usar­lo.

Sin más pro­le­gó­me­no­s: http­s://www.­dol­thu­b.­co­m/­re­po­si­to­rie­s/­ral­si­na/­nom­bres_ar­gen­ti­na_1922_2005/­da­ta/­main

Gra­cias al RE­NA­PER por pu­bli­car es­tos da­tos con una li­cen­cia que me per­mi­te ha­cer­lo.

Mi solución de backup

Intro

¿Los ba­ckups son im­por­tan­tes, ok? Yo lo sé, vos de­be­rías sa­ber­lo. ¿En­ton­ce­s, por qué la ma­yo­ría no tie­ne ba­ckups de­cen­tes de sus com­pus?

Por­que la ma­yo­ría de las ma­ne­ras de ha­cer ba­ckups son in­con­ve­nien­tes o inú­ti­le­s.

Así que acá es­tá la so­lu­ción que yo im­ple­men­té, que ha­ce mis ba­ckups úti­les y con­ve­nien­tes.

La herramienta de backup en sí

Uso res­tic por­que es­tá bue­na. Fun­cio­na, es rá­pi­da, es efi­cien­te con el es­pa­cio, y es fá­ci­l.

Na­da más hay que es­cri­bir un script co­mo es­te:

#!/bin/bash -x

# Backup dónde?
MOUNTDIR=/backup
BACKUPDIR=$MOUNTDIR/backup-$HOSTNAME

if [ -d $BACKUPDIR ]
then
    # Backups con password
    export RESTIC_PASSWORD=passwordgoeshere

    # Backup qué cosa?
    restic -r $BACKUPDIR --verbose backup \
            /home/ralsina \
            --exclude ~ralsina/.cargo \
            --exclude ~ralsina/.local/share/Steam/ \
            --exclude ~ralsina/.cache \
            --exclude ~ralsina/.config/google-chrome/ \
            --exclude ~ralsina/.rustup \
            --exclude ~ralsina/.npm \
            --exclude ~ralsina/.gitbook \
            \
            /etc/systemd/system/backup.* \
            /usr/local/bin

    # Guardar un backup por día de los últimos 7 días que hay backups
    restic -r $MOUNTDIR/backup-pinky forget --prune --keep-daily=7
    # Limpieza
    restic -r $MOUNTDIR/backup-pinky prune
    # Asegurate que están en disco
    sync; sync; sync; sync
fi

La regla 3-2-1 de los backups

Di­ce la re­gla 3-2-1:

  • 3 co­pias de los da­tos (1 ba­ckup pri­ma­rio, dos se­cun­da­rio­s)
  • 2 me­dios de al­ma­ce­na­mien­to dis­tin­to
  • 1 re­mo­to

En mi ca­so, es así:

  • Ba­ckup pri­ma­rio es en el dis­co
  • Ba­ckup se­cun­da­rio es a dis­co en otra má­qui­na (un script si­mi­la­r, usan­do sftp)
  • Ba­ckup ter­cia­rio a un pen dri­ve (me­dio dis­tin­to) que des­pués va en mi bol­si­llo (re­mo­to)

Pa­ra ha­cer los ba­ckups pri­ma­rio y se­con­da­rio son dos ver­sio­nes de ese script (en rea­li­dad el mis­mo scrip­t, con ar­gu­men­to­s).

El ba­ckup ter­cia­rio es un po­co más com­pli­ca­do, por­que quie­ro que sea con­ve­nien­te.

La manera conveniente de hacer backup a un medio removible

Es­ta es mi "u­ser sto­r­y":

Co­mo per­so­na que quie­re un ba­ckup offsi­te pe­ro no tie­ne ga­nas de trans­mi­tir to­dos esos da­to­s, quie­ro en­chu­far un pen dri­ve en la má­qui­na a ba­cku­pear y que AU­TO­MÁ­TI­CA­MEN­TE se ha­ga el ba­ckup de los da­tos al pen dri­ve.

En­ton­ce­s, cuan­do en al­gún mo­men­to el ba­ckup ter­mi­ne, lo pue­do des­en­chu­far y lle­vár­me­lo.

Di­ga­mos que en­con­trar la for­ma de ha­cer eso me to­mó va­rias ho­ras y es­toy bas­tan­te se­gu­ro que mi so­lu­ción es más com­pli­ca­da de lo ne­ce­sa­rio. Pe­ro bue­no, fun­cio­na, así que es­tá bien.

Sien­do es­to Li­nux en el año 2022 ... es­ta so­lu­ción im­pli­ca sys­te­m­d. Y por­que es sys­te­m­d, es com­pli­ca­do.

Automount

Lo primero es montar el pen drive automáticamente en un lugar conocido. Para eso se necesitan dos cosas. Un servicio de automount, para que systemd monte algo en /backup:

/etc/systemd/system/backup.automount

[Unit]
Description=Automount Backup

[Automount]
Where=/backup
TimeoutIdleSec=5min

[Install]
WantedBy=multi-user.target

Y un servicio de mount, para que sepa qué se monta en /backup y cómo:

/etc/systemd/system/backup.mount

[Unit]
Description=Backup
Wants=backup.service
Before=backup.service

[Mount]
What=/dev/disk/by-uuid/74cac511-4d7a-4221-9c0f-e554de12fbf1
Where=/backup
Type=ext4
Options=auto

[Install]
WantedBy=multi-user.target

Las par­tes in­te­re­san­tes so­n:

  • Wants y Before: ese backup.service v a a ser un servicio systemd que efectivamente corre el script de backup. Queremos que lo haga, y que lo haga DESPUÉS de que el pen drive se haya montado.
  • Where y What: "Where" dónde se monta y "What" es el UUID del pen drive como lo muestra sudo blkid

Hay que ha­bi­li­tar e ini­ciar el ser­vi­cio au­to­moun­t, no ha­ce fal­ta ha­cer na­da con el de moun­t.

Por su­pues­to des­pués vie­ne el ser­vi­cio de ba­ckup en sí. Es un "o­nes­ho­t": cuan­do arran­ca eje­cu­ta el script de ba­cku­p:

/etc/systemd/system/backup.service

[Unit]
Description=Backup
Requires=backup.mount
After=backup.mount

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

[Install]
WantedBy=multi-user.target

Hay que ha­bi­lia­tar­lo pe­ro no ha­cer "s­tar­t". Ya que es­tá en el "Wante­d" del moun­t, cuan­do el dis­po­si­ti­vo se mon­ta el ba­ckup se eje­cu­ta.

O ASÍ SE­RÍA EN UN MUN­DO EN EL QUE LAS CO­SAS TIE­NEN SEN­TI­DO

Lamentablemente el dispositivo solo se monta cuando, después de ser insertado, alguien trata de usar el mountpoint. Así que con estos servicios nada pasa hasta que, después de enchufar el pen drive uno va y hace algo como ls /backup, lo que dispara el mount, que a su vez inicia el script de backup.

¿Y cómo se arregla? Ni idea. Mi workaround fue agregar OTROS DOS SERVICIOS, así ls /backup se ejecuta una vez por minuto.

/etc/systemd/system/backup_try.timer

[Unit]
Description=Try to run backup

[Timer]
OnUnitActiveSec=1min

[Install]
WantedBy=timers.target

/etc/systemd/system/backup_try.service

[Unit]
Description=Trigger Backup

[Service]
Type=oneshot
ExecStart=/bin/ls /backup

[Install]
WantedBy=multi-user.target

Y con eso, sí, pue­do en­chu­far el pen dri­ve cuan­do lle­go a la ofi­ci­na a la ma­ña­na y des­en­chu­far­lo más tar­de, sa­bien­do que tie­ne un ba­ckup de hoy aden­tro.

Radxa Zero!

Lo qué?

Las Ras­pbe­rry Pi son úti­le­s, bue­nas y ba­ra­ta­s. Ex­cep­to por un de­ta­lle: es im­po­si­ble com­prar­la­s.

No hay sto­ck de Ras­pbe­rry PI 4, no hay sto­ck de Ras­pbe­rry Pi Ze­ro 2W, no hay sto­ck de na­da, ex­cep­to Pi Pi­co (que son mi­cro­con­tro­la­do­res) y Pi 400 (que no son lo que quie­ro­).

En­ton­ces bus­qué al­ter­na­ti­va­s, y en­contré la bue­na gen­te de All­net Chi­na que ven­de la lí­nea Ro­ck Pi.

¿Cómo son las Rock Pi?

  • Son ... pa­re­ci­das a las Ras­pbe­rry
  • En har­dwa­re, en al­gu­nos ca­so­s, son me­jo­res!
  • En so­ftwa­re ... es­tán un po­co más cru­da­s.
  • En com­pa­ti­bi­li­dad son más com­pli­ca­da­s.

Pe­ro ... HAY STO­CK y A BUEN PRE­CIO y MAN­DAN A AR­GEN­TI­NA!

Así que me com­pre un par de Ra­d­xa Ze­ro­s. Son co­mo una Pi Ze­ro ... pe­ro la CPU es mas o me­nos co­mo la de una Pi 4????

Tu­ve un pro­ble­mi­ta ini­cial­men­te pa­ra pa­gar­lo pe­ro me lo re­sol­vie­ron de in­me­dia­to y me upgra­dea­ron el shi­pping a Fe­dEx, así que lle­ga­ron en dos se­ma­nas y no pa­gué adua­na.

Eso sí, Fe­dEx no te avi­sa que cuan­do te lo traen te van a co­brar "al­go­", y no te di­cen cuán­to ni que te­nés que pa­gar cas­h.

En mi ca­so fue­ron $5400 y no me avi­sa­ron a tiem­po asi que tu­ve que es­pe­rar un día ex­tra.

Y qué tal andan?

Her­mo­so. La CPU es rá­pi­da. Man­ja­ro an­da 10 pun­tos (u­na vez que en­ten­dí co­mo ins­ta­lar­lo­).

Tie­ne eM­MC así que no ne­ce­si­ta tar­je­ta SD!

Un pro­ble­ma es que no he po­di­do ha­cer an­dar mi dis­play 1920­x480 (hay so­lo una men­ción de otra per­so­na en la In­ter­net in­ten­tán­do­lo, tam­po­co le an­du­vo)

Sal­vo eso? Ex­ce­len­te.

Es­toy mi­gran­do mi ser­ver Pi­nky a una Ra­d­xa, ya que la ten­go y con­su­me lo mis­mo que la Pi 3

Si bien leí va­rias ad­ver­ten­cias so­bre que se pue­den re­ca­len­tar no pa­re­cen pa­sar de los 48 gra­dos en uso nor­ma­l.

En ge­ne­ra­l, las re­co­mien­do, pe­ro ca­da uno ten­drá que ver cuán­to quie­re gas­tar y pa­ra qué.


Contents © 2000-2023 Roberto Alsina