Jorge MarotoSoftware Engineer @ Eventbrite. Notes about software, infrastructure and the things I build.https://jorge.maroto.me/enAnalizando los datos de las Oposiciones a Maestros 2022, Comunidad Valencianahttps://jorge.maroto.me/oposiciones-maestros-2022-comunidad-valenciana/https://jorge.maroto.me/oposiciones-maestros-2022-comunidad-valenciana/Hace unos días que han terminado las oposiciones para el cuerpo de maestros en la Comunidad Valenciana , y me picaba la curiosidad de cómo habían ido en función de los tribunales y/o provincias. Antes de nada, decir que Mon, 18 Jul 2022 17:55:30 GMT<p>Hace unos días que han terminado las <strong>oposiciones para el cuerpo de maestros en la Comunidad Valenciana</strong>, y me picaba la curiosidad de cómo habían ido en función de los tribunales y/o provincias.</p><blockquote>Antes de nada, decir que toda esta información es pública en la web de la Conselleria de Educación, <em>Cultura y Deporte de la Generalitat Valenciana</em> (<a href="https://ceice.gva.es/es/web/rrhh-educacion/actas-de-tribunales-de-oposiciones-docentes">link directo</a>), por si alguien quiere acceso a la fuente original.</blockquote><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jorge.maroto.me/content/images/2022/07/image-1.png" class="kg-image"><figcaption>Pantallazo de la web con las actas por especialidad</figcaption></figure><p>Tengo intención de escribir otro <em>blogpost algo más técnico</em> de cómo he conseguido agregar la información – hay <strong>cerca de 4000 archivos PDF</strong>, para las <strong>7 especialidades</strong> y cada uno de los tribunales en las tres provincias (Alicante, Castellón y Valencia)–, pero en éste me quería centrar en comentar los propios datos y dejarlos en formato Google Sheet al final del artículo por si alguien más quiere trastear con ellos.</p><h2 id="an-lisis-de-los-datos">Análisis de los datos</h2><p>Una vez con todos los datos juntos, he realizado algunas agregaciones que me parecieron interesantes para representar en las imágenes que dejo más abajo.</p><h3 id="datos-curiosos">Datos curiosos</h3><ul><li>💃 Con unas 50 personas por tribunal, las especialidades más demandadas fueron <strong>Infantil (147 tribunales y 7376 presentados)</strong> y <strong>Primaria (135 tribunales y 6772 presentados)</strong>.</li><li>🎼 La menos demandada fue la de <strong>Música, con 497 personas</strong> repartidas en 11 tribunales.</li><li>👌 <strong>19 personas en Infantil y 7 en Primaria</strong> han conseguido sacar un 🥇 <strong>10 en ambas partes</strong>. ¡Enhorabuena!</li><li>🔁 El <strong>tribunal V60 de Primaria</strong> es en el que más notas se modificaron, con <strong>19 cambios en el tema, 11 en el caso práctico y 1 en la programación,</strong> aunque sólo 5 de estas personas pasaron de no poder presentarse a la segunda prueba al sí poder hacerlo 🌺.</li></ul><h3 id="resumen-10-0">Resumen 10 / 0</h3><p>A continuación muestro una tabla agrupando a las especialidades por número de 10 en todo (🥇), y 0 en todo (👎).</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/image-3.png" class="kg-image"></figure><h3 id="aprobados-por-tribunal">Aprobados por tribunal</h3><p>En cuanto al número de aprobados por tribunal, lo he separado teniendo en cuenta el conseguir superar cada una de las pruebas, para al menos llegar a presentar la programación, o lo que es lo mismo:</p><ul><li>más de 1,25 en el tema.</li><li>más de 1,25 en caso práctico.</li><li>con lo anterior se superaría la prueba 1 con más de un 2,5.</li><li>más de un 5 en la programación o prueba 2.</li></ul><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/ANGLES.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/AUDICIO-I-LLENGUATGE.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-FISICA.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-INFANTIL--ALICANTE-.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-INFANTIL--CASTELL-N-.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-INFANTIL--VALENCIA-.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-PRIMARIA--ALICANTE-.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-PRIMARIA--CASTELL-N-.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-PRIMARIA--VALENCIA---1-.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/MUSICA.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/PEDAGOGIA-TERAPEUTICA.png" class="kg-image"></figure><h3 id="modificaciones-en-las-calificaciones">Modificaciones en las calificaciones</h3><p>Las siguientes gráficas representan el número de calificaciones que fueron modificadas del listado provisional al definitivo (probablemente tras una reclamación) para cada una de las partes de la prueba.</p><p>Resulta bastante curioso ver el <strong>tribunal V60 para Educación Primaria</strong>, donde en <strong>el tema hubieron 19 modificaciones, en el caso práctico 11 y por último 1 modificación en la prueba 2</strong>.</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/ANGLES-1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/AUDICIO-I-LLENGUATGE-1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-FISICA-1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-INFANTIL--ALICANTE--1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-INFANTIL--CASTELL-N--1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-INFANTIL--VALENCIA--1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-PRIMARIA--ALICANTE--1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-PRIMARIA--CASTELL-N--1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/EDUCACIO-PRIMARIA--VALENCIA--2.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/MUSICA-1.png" class="kg-image"></figure><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2022/07/PEDAGOGIA-TERAP-UTICA.png" class="kg-image"></figure><h2 id="enlaces-de-inter-s">Enlaces de interés</h2><p>Por último, comparto a continuación la web con las actas separadas por especialidad y tribunal, donde hay acceso a cada uno de los PDFs con las calificaciones, así como el Google Sheet que he generado con toda la información agregada.</p><ul><li><a href="https://ceice.gva.es/es/web/rrhh-educacion/actas-de-tribunales-de-oposiciones-docentes">Actas de los tribunales</a> (ceice.gva.es).</li><li><a href="https://docs.google.com/spreadsheets/d/1pAlT-l3rKAiVG9XttO2vgAJ-EpZw0PBNMj98aYJu1gc/edit">Google Sheet con la información agregada</a>.</li></ul>oposicionesdata analyticsMonitoring a Raspberry Pi: Grafana with Prometheushttps://jorge.maroto.me/monitoring-raspberry-pi-grafana/https://jorge.maroto.me/monitoring-raspberry-pi-grafana/In this part, we'll install Grafana with Dokku in our Digital Ocean droplet (5$/month), and after that, use Prometheus as Data Store.Sun, 07 Jun 2020 20:30:00 GMT<p>This is the second part of an article about <strong>how to monitor a Raspberry Pi using Prometheus</strong> and node_explorer. The first part is <a href="https://jorge.maroto.me/monitoring-raspberry-prometheus-node_explorer/">available here</a>.</p><p>In this part, we'll install <a href="https://grafana.com/">Grafana</a> with Dokku in our <a href="https://m.do.co/c/acb59f418e6e" rel="sponsored nofollow"><strong>Digital Ocean</strong> droplet (5$/month)</a>.</p><hr><h2 id="4-install-grafana-in-dokku">4. Install Grafana in Dokku</h2><p>As in the first part we did with prometheus, we'll create the Dokku application, and allow to Grafana to write in the data folder.</p><pre><code># Create the Dokku application
dokku apps:create grafana
# Create the directory where we'll store the prometheus data
mkdir -p /var/lib/dokku/data/storage/grafana/
# The Grafana container uses the user id `472`, so we change the permissions to do that directory writable
# Related: https://github.com/grafana/grafana/blob/293ecbdd4fe1e0b636eb7d0a7e0184ace0f20a80/Dockerfile#L39-L40
sudo chown -R 472:472 /var/lib/dokku/data/storage/grafana/</code></pre><p>In our local, we'll create the git repository, and add the files needed:</p><pre><code class="language-bash"># Initialize the repository
git init
# Add a new remote called `dokku` with our Dokku host
git remote add dokku [email protected]:grafana</code></pre><!--kg-card-begin: markdown--><ul>
<li><code>Dockerfile</code> (using the Grafana as base, we'll include the specific configuration for nginx)</li>
<li><code>nginx.conf.sigil</code> (just to increase the size limit when we do POST using grafana, for example to do snapshots of some dashboard).</li>
<li><code>app.json</code> (optional, but I'm using the <a href="https://github.com/crisward/dokku-require">dokku-require</a> plugin, this file configures the mounted volumes).</li>
</ul>
<!--kg-card-end: markdown--><figure class="kg-card kg-code-card"><pre><code class="language-docker">FROM grafana/grafana:7.0.3
COPY ./nginx.conf.sigil .
</code></pre><figcaption>Dockerfile</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-nginx">...
...
client_max_body_size 250m;
...
...</code></pre><figcaption>nginx.conf.sigil</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-json">{
"dokku": {
"volumes": [
{
"host": "/var/lib/dokku/data/storage/grafana/data",
"app": "/var/lib/grafana",
"phases": "run,deploy"
}
]
}
}
</code></pre><figcaption>app.json</figcaption></figure><p>As we're using a Dockerfile Deployment, we're adding this <a href="https://github.com/gliderlabs/sigil">sigil template</a> to our application WORKDIR</p><!--kg-card-begin: markdown--><p>As we're using a Dockerfile Deployment, we're adding this <code>sigil template</code> to our application <code>WORKDIR</code>. It's a copy from the <a href="https://github.com/dokku/dokku/blob/master/plugins/nginx-vhosts/templates/nginx.conf.sigil">default template</a>, just adding the <code>client_max_body_size</code> config, which allows to <code>POST</code> bigger requests, for example when we'll export a Grafana snapshot.</p>
<!--kg-card-end: markdown--><p>After push to our Dokku repository, we'll be able to connect using the default domain and port, but we could setup those:</p><pre><code class="language-bash">dokku domains:add grafana grafana.mydomain.com
dokku proxy:ports-set grafana http:80:3000
dokku letsencrypt grafana</code></pre><p>You can open now Grafana.mydomain.com in your browser, and introduce the default user: <em>admin</em> / <em>admin</em>.</p><h2 id="5-connecting-grafana-to-prometheus">5. Connecting Grafana to Prometheus</h2><p>Grafana and Prometheus are working in two different containers, so if we want that Grafana read the data from Prometheus, we have to connect both networks.</p><p>Using Dokku, it's easy to create a new network, and use it in both containers:</p><pre><code class="language-bash">dokku network:create grafana-prometheus
dokku network:set prometheus attach-post-create grafana-prometheus
dokku network:set grafana attach-post-create grafana-prometheus
# After that, we could see a report of the networks per application
dokku@ubuntu-dokku:~$ dokku network:report prometheus
=====> prometheus network information
Network attach post create: grafana-prometheus
Network attach post deploy:
Network bind all interfaces: false
Network web listeners: 172.17.0.7:9090
# But we could use also the name of the container, for example: http://prometheus.web.1:9090</code></pre><p>With this URL, we can create a new datasource from our Grafana website: https://grafana.mydomain.com/datasources, adding the URL of Prometheus.</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/06/image.png" class="kg-image"></figure><p>After that, we can start to do some queries over prometheus, <a href="https://prometheus.io/docs/prometheus/latest/querying/examples/">there are a bunch of examples on their website</a>.</p><h2 id="6-importing-a-node_exporter-dashboard">6. Importing a node_exporter dashboard</h2><p>An interesting feature of Grafana, is the capability to import dashboards, even they have a repository with a lot of these.</p><p>Thanks to that, we can find a <a href="https://grafana.com/grafana/dashboards/1860">Node Exporter Full dashboard</a>, which we could import just using the ID (<em>1860</em>) in https://grafana.mydomain.com/dashboard/import, and we'll have a dashboard like the following.</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/06/Screenshot-2020-06-08-at-00.59.38-1.png" class="kg-image"></figure><h2 id="recap">Recap</h2><p>In this part, we've discovered how to install Grafana in Dokku, and also how to connect it to the Prometheus installed <a href="https://jorge.maroto.me/monitoring-raspberry-prometheus-node_explorer/">in the first part of this article</a> to use as a data source.</p><p>As you've seen, this is a cheap way to get monitored a server, from a Raspberry Pi in your home, to a more professional setup in your company, because you can even define alarms to get notified when something is going wrong.</p><h2 id="references">References</h2><ul><li>Grafana: <a href="https://grafana.com/grafana/dashboards/1860">Node Exporter Dashboard</a></li><li>Github: <a href="https://github.com/fahlke/raspberrypi_exporter/pull/1/files">raspberry_exporter</a></li></ul>dokkugrafanaprometheusdockerMonitoring a Raspberry Pi with Prometheus & node_exporter in Dokkuhttps://jorge.maroto.me/monitoring-raspberry-prometheus-node_explorer/https://jorge.maroto.me/monitoring-raspberry-prometheus-node_explorer/This article explains how to install node_exporter in a Raspberry Pi, and Prometheus using Dokku.Sun, 07 Jun 2020 20:00:00 GMT<p></p><p>The last weeks, I've been having some issues with my Raspberry Pi, which unexpectedly stopped working after some days, so I asked a question on twitter, and the following stack was one of the proposals.</p><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet" data-width="550"><p lang="es" dir="ltr">Desde hace unos días se me está quedando frita la raspberry donde tengo montado <a href="https://twitter.com/hashtag/homeAssistant?src=hash&ref_src=twsrc%5Etfw">#homeAssistant</a>, y no se muy bien el por qué.<br><br>De momento estoy usando @StatusCakeTeam para enterarme, pero no veo un patrón, así que voy a empezar a monitorizar tb los clásicos de CPU/Mem</p>— Jorge (en fase 1) (@patoroco) <a href="https://twitter.com/patoroco/status/1269230080053706753?ref_src=twsrc%5Etfw">June 6, 2020</a></blockquote>
</figure><p><a href="https://prometheus.io/">Prometheus</a> is one of the most popular options when you think in a monitoring solution (time series based, alerting, etc), and one of their sub-projects is <a href="https://github.com/prometheus/node_exporter">node_exporter</a>, which shows a list of metrics that will be consumed by Prometheus.</p><p>Dokku is <em>The smallest PaaS implementation you've ever seen</em>, and I've blogged about it <a href="https://jorge.maroto.me/tag/dokku/">several times because I'm using it for all my personal projects</a> hosted in the smallest dropplet in <a href="https://m.do.co/c/acb59f418e6e" rel="sponsored nofollow"><strong>Digital Ocean</strong> (5$/month)</a>.</p><p>I've divided this article in two different posts, and these are all the parts:</p><!--kg-card-begin: markdown--><ol>
<li>Export the metrics from the Raspberry Pi using <code>node_exporter</code>.</li>
<li>Do the metrics accessible from internet (as we'll run Prometheus in a Digital Ocean dropplet).</li>
<li>Install Prometheus in dokku.</li>
<li>Install Grafana in dokku.</li>
<li>Connect all the pieces.</li>
<li>Importing a <code>node_exporter</code> dashboard.</li>
</ol>
<!--kg-card-end: markdown--><h2 id="1-exporting-the-metrics">1. Exporting the metrics</h2><!--kg-card-begin: markdown--><p><a href="https://github.com/prometheus/node_exporter"><code>node_exporter</code></a> is a small application that exposes several metrics in a format that Prometheus is able to pull.<br>
The installation is straightforward, and consists in download the package from <a href="https://github.com/prometheus/node_exporter/releases">the releases tab in Github</a>, and execute it (these commands are run in your RPi).</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-code-card"><pre><code class="language-bash"># Download the package
wget https://github.com/prometheus/node_exporter/releases/download/v1.0.0/node_exporter-1.0.0.linux-armv7.tar.gz
# Extract the package
sudo tar -xvf node_exporter-1.0.0.linux-armv7.tar.gz -C /usr/local/bin/ --strip-components=1
# Run the node_exporter
node_exporter</code></pre><figcaption>In my case, as I have the Raspberry Pi model 3, so I've downloaded the ARMv7 release from the list.</figcaption></figure><p>Once you run the command, you could visit <em>http://<raspberry_IP>:9100/</em>, and press in the <strong>metrics</strong> button, in my case it will link to http://192.168.0.166:9100/metrics.</p><figure class="kg-card kg-code-card"><pre><code class="language-text"># HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 9.0365e-05
go_gc_duration_seconds{quantile="0.25"} 0.000183073
go_gc_duration_seconds{quantile="0.5"} 0.000413749
go_gc_duration_seconds{quantile="0.75"} 0.0005413
go_gc_duration_seconds{quantile="1"} 0.012291414
go_gc_duration_seconds_sum 2.396249156
go_gc_duration_seconds_count 4209
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 10
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.14.3"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 3.897568e+06
...
...</code></pre><figcaption>These are the first lines that node_exporter includes</figcaption></figure><p>You don't want to run this command manually every time that your raspberry needs to restart, so you can add an entry to your crontab:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">crontab -e
# Add the following line to your crontab and save the file
@reboot /usr/local/bin/node_exporter</code></pre><figcaption>You can reboot your RPi, and check that it autostart as you expected</figcaption></figure><h2 id="2-doing-accessible-node_exporter-from-internet">2. Doing accessible node_exporter from Internet</h2><p>As we'll have our Prometheus hosted in an external server (<a href="https://m.do.co/c/acb59f418e6e" rel="sponsored nofollow">Digital Ocean</a> in my case), we have to do our RPi accessible from the internet.</p><!--kg-card-begin: markdown--><p>Doing that could be different depending on the router you have, so I gonna share a screenshot of my router's configuration, where it's only needed to set up the port to be mapped to the RPi, in my case, accessing to <code><my_ip>:9101</code> from the internet, will be mapped to the port <code>9100</code> on my RPi.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/06/Screenshot_07_06_2020__23_05.png" class="kg-image"></figure><h2 id="3-install-prometheus-in-dokku">3. Install Prometheus in Dokku</h2><p>I'm going to explain how to deploy Prometheus in that droplet using Dokku.</p><pre><code class="language-bash"># Create the dokku application
dokku apps:create prometheus
# Create the directory where we'll store the prometheus data
mkdir -p /var/lib/dokku/data/storage/prometheus/
# The prometheus container uses the user `nobody`, so we change the permissions to do that directory writable
# Related: https://github.com/prometheus/prometheus/blob/e963d953eac7d5181024eba2215740835b65c0a9/Dockerfile#L18-L21
sudo chown -R 65534:65534 /var/lib/dokku/data/storage/prometheus/</code></pre><p>In our local, we create a new repository and setup a remote with our dokku host.</p><pre><code class="language-bash"># Initialize the repository
git init
# Add a new remote called `dokku` with our dokku host
git remote add dokku [email protected]:prometheus
</code></pre><p>Now, we have to create the minimum docker environment:</p><!--kg-card-begin: markdown--><ul>
<li><code>Dockerfile</code> (using the prometheus image as base, and just copying the config).</li>
<li><code>prometheus.yml</code> (with the config to scrape).</li>
<li><code>app.json</code> (optional, but I'm using the <a href="https://github.com/crisward/dokku-require">dokku-require</a> plugin, this file configures the mounted volumes).</li>
</ul>
<!--kg-card-end: markdown--><figure class="kg-card kg-code-card"><pre><code class="language-docker">FROM prom/prometheus
COPY ./prometheus.yml /etc/prometheus/prometheus.yml
</code></pre><figcaption>Dockerfile</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-yml">global:
scrape_interval: 15s # Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "Raspberry"
static_configs:
- targets: ["<your_public_ip_address>:9101"]
</code></pre><figcaption>prometheus.yml</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-json">{
"dokku": {
"volumes": [
{
"host": "/var/lib/dokku/data/storage/prometheus/data",
"app": "/data/",
"phases": "run,deploy"
}
]
}
}
</code></pre><figcaption>app.json</figcaption></figure><p>After commit all these files, and push to the dokku server, you should be able to access to the prometheus in the default domain value, but maybe you prefer to access in a more friendly url, like https://prometheus.yourdomain.com:9091/.</p><pre><code class="language-bash"># Configure your desired domain
dokku domains:add prometheus prometheus.yourdomain.com
# Enable the HTTPS using the letsencrypt plugin
dokku letsencrypt prometheus
# Set the proxy ports
dokku proxy:ports-set prometheus http:9090:9090 https:9091:9090</code></pre><p>The last step, is just to configure the start parameter that prometheus will use to run the container (more info about the available parameters in <a href="https://prometheus.io/docs/prometheus/latest/storage/#operational-aspects">the prometheus website</a>):</p><pre><code>dokku config:set prometheus DOKKU_DOCKERFILE_START_CMD="--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/data --storage.tsdb.retention.size=1GB --storage.tsdb.retention.time=30d"</code></pre><!--kg-card-begin: markdown--><p>After that, if you open https://prometheus.yourdomain.com:9091/ in your browser, you should see something similar to this under the <code>Status > Targets</code> menu.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jorge.maroto.me/content/images/2020/06/Screenshot_08_06_2020__00_04.png" class="kg-image"><figcaption>List of targets managed by prometheus</figcaption></figure><p>And you could start to play with the available metrics from the Graph menu (<a href="https://prometheus.io/docs/prometheus/latest/querying/examples/">prometheus query examples</a>).</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/06/Screenshot_08_06_2020__00_08.png" class="kg-image"></figure><h2 id="recap">Recap</h2><p>In this article we've learned how to consume the metrics that node_exporter generates from our Raspberry Pi, and querying these using prometheus.</p><p>In <a href="https://jorge.maroto.me/monitoring-raspberry-pi-grafana/">the next article</a> I'll explain how to install Grafana in Dokku, and how to connect all the pieces.</p><h2 id="references">References</h2><ul><li>Prometheus :: <a href="https://prometheus.io/docs/prometheus/latest/storage/#operational-aspects">Storage Configuration</a>.</li><li>Tutorial: <a href="https://linuxhit.com/prometheus-node-exporter-on-raspberry-pi-how-to-install/">Node Exporter in Raspberry Pi</a>.</li><li>Github: <a href="https://github.com/fahlke/raspberrypi_exporter/pull/1/files">raspberry_exporter</a>.</li></ul>dokkumonitoringprometheusraspberry pidockerUsing Youtube on iOS while the screen is offhttps://jorge.maroto.me/using-youtube-on-ios-while-screen-is-off/https://jorge.maroto.me/using-youtube-on-ios-while-screen-is-off/As Youtube has disabled playing videos in background, using Youtube BG shortcut, you will be able to run Youtube videos in background mode from the "Share menu" in the youtube app.Sun, 23 Jun 2019 11:00:00 GMT<p>Some months ago Youtube presented <code>Youtube Premium</code>, a suscription plan that between more features, allows you to continue using video in background mode (while you're viewing another app or when you decide turn off the screen).</p><p>This easy tweak will allow you to continue seeing Youtube videos in background as you did in the past, and everything without require Jailbreak for your iPhone / iPad.</p><p>TL;DR; using <a href="https://maroto.me/youtube-bg">Youtube BG shortcut</a>, you will be able to run Youtube videos in background mode from the "Share menu" in the youtube app.</p><h2 id="requirements">Requirements</h2><ol><li>Install <a href="https://apps.apple.com/us/app/shortcuts/id915249334">Shortcurts app from the AppStore</a>.</li><li>From the official Youtube app, press the three dots to show the "Sharing", and once in, press the <code>More</code> button on the bottom-rigth, and again, <code>More</code> in the share menu.</li></ol><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/05/2019-06-23-enable-shortcuts-1.gif" class="kg-image"></figure><p>3. Install the <a href="https://maroto.me/youtube-bg">Youtube BG shortcut pressing here</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jorge.maroto.me/content/images/2020/05/2019-06-23-using-youtube-bg.gif" class="kg-image"><figcaption>** Note: if the video sound stops, you can press play from the bottom menu (as when you want to change a song from Spotify), and it will play in background mode.</figcaption></figure><h2 id="how-it-works">How it works</h2><p>Thanks to <a href="https://ytdl-org.github.io/youtube-dl/index.html"><code>youtube-dl</code></a>, I'll get the raw-video URL, and using the iOS app <a href="https://apps.apple.com/us/app/shortcuts/id915249334">Shortcuts</a>, you will be able to run all the flow from the sharing menu of the official Youtube app.</p>iOSshortcutsyoutubeWeCode' talk about Dokkuhttps://jorge.maroto.me/wecode-talk-about-dokku/https://jorge.maroto.me/wecode-talk-about-dokku/Talk about Dokku at WeCode (spanish). Dokku is a pretty tool to create a PaaS (Platform as a Service) in yourself instanceThu, 28 Mar 2019 18:53:00 GMT<p><a href="https://wecodefest.com/">WeCode</a> is a really nice conference in Valladolid (Spain) where some slots are opened to present yourself talks, so I decided to talk about one of my last toys: Dokku.</p><p>There is the video of the talk (Spanish), and <a href="https://docs.google.com/presentation/d/18ejgt1MvYEK0-pa7t4HHKUHsXgoHDzbYDhcMXn19MVo/edit?usp=sharing">the slides</a>.</p><figure class="kg-card kg-embed-card"><iframe width="612" height="344" src="https://www.youtube.com/embed/fAEO8nLHXPI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure>talksdokkuScaling Amazon Aurora at ticketeahttps://jorge.maroto.me/scaling-amazon-aurora-at-ticketea/https://jorge.maroto.me/scaling-amazon-aurora-at-ticketea/Ticketing is a business in which extreme traffic spikes are the norm, rather than the exception. For Ticketea, this means that our traffic can increase by a factor of 60x in a matter of seconds. This usually happens when big events (which have a fixed, pre-announced 'sale start time') go on sale.Fri, 19 May 2017 12:00:00 GMT<p>I wrote a post about how we scaling AWS Aurora at ticketea when we go to sell some big event.</p><p>Originally it was available on our engineering blog: <strong>Scaling Amazon Aurora at ticketea</strong>, but I gonna include in this blog too.</p><hr><p>Ticketing is a business in which extreme traffic spikes are the norm, rather than the exception. For <strong>Ticketea</strong>, this means that <strong>our traffic can increase by a factor of 60x</strong> in a matter of seconds. This usually happens when big events (which have a fixed, pre-announced <em>'sale start time'</em>) go on sale.</p><p>Cloud elasticity has its limits, particularly when reacting to extremely sudden changes in the inbound request rate. This is the reason why, for certain situations, we prefered to perform a pre-planned platform scaling followed by a warm-up.<br>For the sake of context, we host our infrastructure in AWS ad we're heavy Amazon Aurora users.</p><p>For Ticketea, a big event usually translates to a surge of traffic, which touches the following components:</p><ul><li>Frontend app servers serving ticketea.com</li><li>API app servers</li><li>Background tasks</li><li>Relational Databases</li></ul><p>The first three resources are easy to scale horizontally (add / remove EC2 instances). We just need to modify <a href="http://docs.aws.amazon.com/autoscaling/latest/userguide/AutoScalingGroup.html">their autoscaling groups</a>, and AWS will do the hard work for us.</p><p>Relational databases are usually much harder to scale. Even though we're using an AWS Aurora cluster, with multiple read replicas, scaling up and down the writer node is usually the tricky part. Before we get into it, let's talk a bit about AWS Aurora and how we're using it.</p><p>An Aurora cluster is accessible through two DNS records:</p><ul><li>A writer endpoint (a DNS Record pointing to the currently elected writer node)</li><li>A reader endpoint (a DNS Record which balances among the reader instances)</li></ul><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/05/rds_diagram-1.jpg" class="kg-image"></figure><h2 id="understanding-the-failover-process"><strong>Understanding the failover process</strong></h2><p>Failover is the process that Amazon Aurora gives us to promote a node to the writer role (Aurora only allows one writer at a time). The choice of the <em>future writer node</em> is performed using <strong>tiers</strong>. A tier is a config value which is set at instance creation time (and can be changed later).</p><p>When a failover happens (either manually triggered or in reaction to a cluster failure) Aurora will promote the lowest-tier reader node to the writer role.</p><p>As stated before, sometimes we need to scale the writer node vertically. To achieve this result, we force a failover to a beefier instance. Traditionally, we used to do this when the traffic was at its lowest point during the day, because we were afraid of the impact that such operation might have had on our users.<br>That really didn't work out well for the team (it meant that someone had to wake up early / stay up late), so we decided do some tests to understand how to improve the failover and recovery times.</p><p>The first step was a simple script that issued bursts of queries to the writer node. During the execution, we would perform a manual failover, at which point we'd start to see that some of queries were OK, but others failed <em>randomly</em>. The errors lasted during a 10-15 second window. We repeated the test several times, and results were similar.</p><p>We decided to investigate how the Aurora writer and reader endpoints were implemented. Running <code>host</code> on the writer endpoint DNS record (let's suppose <code>tkt-aurora-cluster.cluster-abcdefg.eu-west-1.rds.amazonaws.com</code>), reveals that the endpoint is really a <code>CNAME</code> pointing to the currently elected Aurora writer instance.</p><pre><code class="language-bash">$ host tkt-aurora-cluster.cluster-abcdefg.eu-west-1.rds.amazonaws.com
tkt-aurora-cluster.cluster-abcdefg.eu-west-1.rds.amazonaws.com is an alias for
tkt-aurora-1.abcdefg.eu-west-1.rds.amazonaws.com
tkt-aurora-1.abcdefg.eu-west-1.rds.amazonaws.com is an alias for ec2-12-123-12-12.eu-west-1.compute.amazonaws.com.
ec2-12-123-12-12.eu-west-1.compute.amazonaws.com has address 12.123.12.12</code></pre><p>The reader endpoint works in a similar fashion, with the exception that it's backed by a <em>Round-Robin</em> DNS record pointing to the underlying database instances.</p><p>This explains why we were getting some errors during the failover operation: there is a rather large window of time (10-15 seconds) during which the cluster is adjusting to the new topology and DNS records are switched to reflect it. As you can imagine, DNS manipulation and propagation is not an atomic operation, hence the errors.</p><h2 id="scaling-procedures"><strong>Scaling procedures</strong></h2><p>Once we gathered more information with this small research, we defined four different processes to scale our platform while minimizing the impact on our users. Let's have a look at them.</p><h3 id="horizontal-scaling-of-the-read-cluster"><strong>Horizontal scaling of the read cluster</strong></h3><p>This means adding or removing nodes to our read cluster to increase our read capacity.</p><h4 id="scaling-out"><strong>Scaling out</strong></h4><p>Scaling out is really easy: If you use the AWS Console, you can pick your cluster and choose the <em>Create New Aurora Replica</em> option. In our case, <strong>a new read replica takes ~7 minutes to be ready</strong>, and this operation doesn't cause downtime of any sort. The new node will not be added to the reader DNS endpoint until fully ready.</p><h4 id="scaling-in"><strong>Scaling in</strong></h4><p>This is actually a bit tricky. If we have 3 reader instances, and we decide to terminate one of them, the DNS round-robin will propagate with a certain delay, resulting in traffic being delivered to a dead database instance during a certain period of time.</p><p>Due to that, we decided to use an additional DNS record in <code>Route53</code>. This DNS record is the hostname applications normally connect to. It normally points to the cluster reader endpoint, except during a scale-in operation. In that case, we temporarily point it to a specific database reader instance, while others are being deleted.</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/05/scale_in.jpg" class="kg-image"></figure><p>In this way we have exact control over the node where the read traffic is routed to, instead of relying on DNS propagation.</p><h3 id="vertical-scaling-of-the-writer-node"><strong>Vertical scaling of the writer node</strong></h3><p>Since Amazon Aurora is not multi-master, if we need more write capacity, we need to change the writer instance type. This means that we need to create a new Aurora instance with a higher capacity and then promote it to the writer role.</p><h4 id="scaling-up"><strong>Scaling up</strong></h4><p>To have more control over the scale-up process, we usually create a new node with more capacity (let's name it <em>new_master</em>). It will be given the <strong>tier 0</strong> which means it'll be the first candidate for promotion to the writer role. As explained in the scale-out section, this process takes ~7 minutes with our main database.</p><p>After that, we perform a manual failover on the cluster, which will promote <em>new_master</em> to writer. Due to DNS propagation delay, it's possible to see some errors during a window of 10-15 seconds (but your application is resilient to these errors, isn't it? :p)</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/05/sentry.jpg" class="kg-image"></figure><h3 id="scaling-down"><strong>Scaling down</strong></h3><p>This process is the inverse of scaling up. We only modify our <em>old_master</em> instance to have tier 0, and perform the cluster failover. Again, it's possible to see some errors during a 10-15 second window.</p><h2 id="final-conclusions"><strong>Final conclusions</strong></h2><p>Amazon Aurora clusters are managed with CNAME records which point to database instances. It is important to understand how they work to be able to minimize the impact of failover operations.</p><p>Having an additional Route53 record gives us more control during the scale-in operation, and it doesn't make the architecture more complex.</p><p>We're currently performing these processes manually, which means we're still not 100% satisfied with the solution. We have some ideas, but if you have any suggestions, feel free to leave a comment! Also, if you happen to be interested in this sort of scalability and reliability topics, keep in mind that we're hiring :-)</p>ticketeaAWSRDSUIActivityViewController workaround to 'Share in WhatsApp' in iOShttps://jorge.maroto.me/uiactivityviewcontroller-workaround-to-share-in-whatsapp-in-ios/https://jorge.maroto.me/uiactivityviewcontroller-workaround-to-share-in-whatsapp-in-ios/Workaround to be able to use 'Share in WhatsApp' in iOSThu, 19 May 2016 19:06:00 GMT<p><code>UIActivityViewController</code> was introduced in <strong>iOS 6</strong> as a helper to share texts, links or images between apps.</p><p>It's really easy to work with default services (share on Twitter, Facebook, Mail…), and since several iOS versions, it's also integrated with third-party apps like Slack or Telegram.</p><p>Use it is simple, you only need to create and present a <code>UIActivityViewController</code> as follows:</p><pre><code class="language-objc">UIViewController *root = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
UIActivityViewController *activityView = [[UIActivityViewControllerWithoutWhatsApp alloc] initWithActivityItems:shareObject applicationActivities:nil];
[root presentViewController:activityView animated:YES completion:nil];
</code></pre><p>A typical setup looks like that, but sometime you don't want to allow to send SMS, or Mails from your action, so you can set an array of <code>excludedActivityTypes</code> as follows:</p><pre><code class="language-objc">activityView.excludedActivityTypes = @[UIActivityTypeMessage, UIActivityTypeMail];</code></pre><p>There are several 'built-in' activities, but you can craft yourself <code>UIActivity</code> to do specific actions, a good compilation is available in <a href="https://github.com/shu223/UIActivityCollection">Github/UIActivityCollection</a>.</p><p>In our case, and because we suffered <a href="http://stackoverflow.com/a/36856840">a bug related with last WhatsApp version</a>, which showed a message when try to share with one of your whatsapp contacts:</p><blockquote>This item cannot be shared. Please select a different item.</blockquote><p>We decided to workaround it using <code>URLSchemes</code>, and we found <a href="https://github.com/sascha/SSCWhatsAppActivity"><code>SSCWhatsAppActivity</code></a>, a <code>UIActivity</code> subclass which shows an icon on share menu, but it appeared next to the original whatsapp icon, so we needed to remove this first.</p><p>As logic indicated, we looked for whatsapp activity identifier, and add to excludeActivityTypes array as follows:</p><pre><code class="language-objc">activityView.excludedActivityTypes = @[@"net.whatsapp.WhatsApp.ShareExtension"];</code></pre><p>But <strong>it’s not possible to remove third-party activities from menu</strong>, at least directly. So, after play some minutes with <code><objc/runtime.h></code>, we finally found a private method which seemed to be related with our purpose: <code>_shouldExcludeActivityType</code>:</p><pre><code class="language-objc">#import "UIActivityViewControllerWithoutWhatsApp.h"
@interface UIActivityViewController (Private)
- (BOOL)_shouldExcludeActivityType:(UIActivity*)activity;
@end
@implementation UIActivityViewControllerWithoutWhatsApp
- (BOOL)_shouldExcludeActivityType:(UIActivity *)activity
{
if ([[activity activityType] isEqualToString:@"net.whatsapp.WhatsApp.ShareExtension"]) {
return YES;
}
return [super _shouldExcludeActivityType:activity];
}
@end</code></pre><p>And, you know what? It works! Thanks Apple to do that so straightforward.</p>iOSPucela Testing Days. Testing iOS Applicationshttps://jorge.maroto.me/pucela-testing-days-testing-ios-applications/https://jorge.maroto.me/pucela-testing-days-testing-ios-applications/Talk in Cylicon Valley about iOS applications testing.Sat, 30 Nov 2013 20:12:00 GMT<p>As some of you know, I usually assist to <a href="https://cyliconvalley.es/">Cylicon Valley</a>, a developer community at Castilla y León.</p><p>This month, we organized a serie of talks about testing named <em>Pucela Testing Days</em> (<a href="https://web.archive.org/web/20170701180811/http://agilecyl.org/2013/11/27/pucelatestingdays-testing-en-ios-y-testing-en-android/">webarchive</a>), so I've collaborated talking about state of the art of iOS testing.</p><p>There is the video (sorry about the quality, but I recorded it myself, so please, attend to the sound and check the slides).</p><figure class="kg-card kg-embed-card"><iframe width="459" height="344" src="https://www.youtube.com/embed/6ruv6vMUTtE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><figure class="kg-card kg-embed-card"><iframe id="talk_frame_78800" src="https://speakerdeck.com/player/44cbde103ce101318fc01afd74a057dc" width="1280" height="960" style="border:0; padding:0; margin:0; background:transparent;" frameborder="0" allowtransparency="true" allowfullscreen="allowfullscreen" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
</figure>talksiOStestingCylicon ValleyCodemotion 2013. Introduction to Cocoa Podshttps://jorge.maroto.me/codemotion-2013-introduction-to-cocoa-pods/https://jorge.maroto.me/codemotion-2013-introduction-to-cocoa-pods/Comments after my talk in Codemotion Madrid 2013 about Cocoa Pods.Sun, 20 Oct 2013 08:38:00 GMT<p>As <a href="https://jorge.maroto.me/codemotion-2013/">I announced some weeks ago</a>, I was in Codemotion talking about Cocoa Pods. If you want to start to use this useful ruby gem, check my slides (spanish)!</p><figure class="kg-card kg-embed-card"><iframe id="talk_frame_78804" src="https://speakerdeck.com/player/3b3986b03ce20131a8d62e270ad3f858" width="1280" height="960" style="border:0; padding:0; margin:0; background:transparent;" frameborder="0" allowtransparency="true" allowfullscreen="allowfullscreen" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
</figure>conferencescodemotioniOStalksCocoaPodsNSSpain 2013https://jorge.maroto.me/nsspain-2013/https://jorge.maroto.me/nsspain-2013/Reflexions about my participation in NSSpain 2013 as volunteer. See you next year!Fri, 20 Sep 2013 10:01:00 GMT<p>Few months ago was when I first read on twitter about 'the first iOS-dev conference' in Spain. At first it seemed <em>another</em> conference with some popular spanish developers talking about common topics, but when organizers started to show who were coming, I realized that it would not be a typical meeting.</p><p>First surprising thing was that ALL the talks would be in English, and that was because many of the speakers would be <em>international celebrities</em>, so the event would be followed around the world.</p><p>Second interesting thing for me was that it would be a four-days event, something very different from events as I usually assist, so with so long is possible to talk freely with speakers and enjoy of Logroño’s night in their patron’s saint day, this was third reason to finally contact with Borja & Luis (organizers) asking about posibility to be volunteer, result is below (thanks for the photo <a href="https://twitter.com/juanriaza/status/384701058926514176/photo/1">@juanriaza</a>) ;)</p><p>To be volunteer allowed me to be in contact with all people, and I enjoyed it because I also attended many talks with VERY smart people as <a href="http://twitter.com/orta">@orta</a> & <a href="http://twitter.com/fabiopelosin">@fabiopelosin</a> talking about our loved CocoaPods, <a href="http://twitter.com/nachosoto">@NachoSoto</a> explaining how to improve our Core Animations with a quick review of different ways to do that, or <a href="http://twitter.com/steipete">@steipete</a>, talk which I could not attend, but where people’s head explode trying to understand how obj-c runtime works.</p><p>If you want, I started a compilation with some of the slides of this NSSpain which is available on my gist <a href="https://github.com/NSSpain/NSSpain-Summaries/blob/master/2013.md">NSSpain-Summaries</a>. I can only recommend you that next year assist, and see you there :).</p>iOSNSSpainconferencesCodemotion 2013https://jorge.maroto.me/codemotion-2013/https://jorge.maroto.me/codemotion-2013/Some comments about Codemotion 2013 in MadridFri, 13 Sep 2013 08:01:00 GMT<p><strong>Codemotion</strong> is an event to meet up with developers of different technologies and places which takes place in several countries (look all at <a href="http://www.codemotionworld.com/">Codemotion World</a>).</p><p>Last year was the first event on Spain, and I was there as public, even recording some videos about <a href="https://vimeo.com/39783731">storyboard on XCode</a> or <a href="https://vimeo.com/39267868">how to monetize apps</a>. I also saw some talks about Cocos 2D or development for Kinect, but unfortunately my iPhone's battery does not last as long as I wanted...</p><p>This year I decided to send a talk when they opened call-for-papers, and this has been included in the schedule!</p><p>If you want to learn a little bit <strong>about what is Cocoa Pods</strong>, I'll be happy that you attend to the talk, <strong>19th October, 11:30 - 12:15 in track 6</strong> <a href="https://web.archive.org/web/20140407042609/http://codemotion.es/talk/19-october/26">webarchive::codemotion.es</a>.</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2020/05/image.png" class="kg-image"></figure><p>See you there! :)</p>talksCocoaPodsiOSEditing 404 page on Github pageshttps://jorge.maroto.me/editing-404-page-on-github-pages/https://jorge.maroto.me/editing-404-page-on-github-pages/By default Octopress doesn't include a 404 page, so on Github appear a default page. Here we go to configure one.Sun, 08 Sep 2013 09:52:00 GMT<p>By default Octopress doesn't include a 404 page, so on Github it's showed as follows:</p><figure class="kg-card kg-image-card"><img src="https://jorge.maroto.me/content/images/2013/20130908-404github.png" class="kg-image" alt="404 github"></figure><p>Usually with a rack server it's needed to modify <code>config.ru</code> file to manage exceptions (this web explain this case), but in my case, I can not manage <em>server side</em>, so Github give us another way: they interpret a 404.html file as a default 404 page, as you can read on <a href="https://help.github.com/articles/custom-404-pages">their documentation</a>.</p><p>In summary, you need to create a new file at path <code>sources/404.html</code> and it will be used as 404. You can see how mine is in 404.html, and that's the code:</p><pre><code class="language-md">---
layout: default
---
<h1 style="text-align: center">Page not found</h1>
<p style="text-align:center">You can find other posts on <a href="https://jorge.maroto.me/archives">Archives</a> of this blog, or directly go to <a href="https://jorge.maroto.me/">the main page</a></p>
<img src="https://jorge.maroto.me/images/404.png" style="max-width: 100%; margin: 0 auto; display: block" />
<small style="display:block; float:right">Credits of the image: <a href="http://refinedmobile.com/404">refinedmobile.com</a></small>
</code></pre>blogoctopressgithubConfiguring Octopresshttps://jorge.maroto.me/some-configurations-that-i-did-to-my-octopress/https://jorge.maroto.me/some-configurations-that-i-did-to-my-octopress/Some configurations that I did to my octopress.Sat, 07 Sep 2013 19:15:00 GMT<p>On the last post I talked about <a href="https://jorge.maroto.me/deploying-octopress-on-github-with-your-domain/">how to deploy octopress on github with your custom domain</a>, but it needs a little bit config to be as I like, you can see more info about that on <a href="http://octopress.org/docs/configuring/">Octopress configuration</a>, but if you want to know which steps I followed, open <code>_config.yml</code> file and modify this lines:</p><pre><code class="language-yaml">...
permalink: /:year/:month/:day/:title/
...
category_dir: categories
...
paginate: 5
pagination_dir: # It's blank because I don't want /blog before each link page
</code></pre><p>I found a post about SEO for Octopress websites which explain why and how remove redundant /blog prefix, so I followed it :).</p><p>After that, appears a section with 3rd party settings for different social networks and services. I think that there are self-explanatory, so I'll just give a tips:</p><ul><li><a href="http://ansonalex.com/google-plus/how-do-i-find-my-google-plus-user-id-google/">How do you find your G+ user id?</a></li><li>Octopress is a static blog, so if you want to have comments, you need to use some like Disqus, it's easy (and free!) create an account, so visit <a href="http://disqus.com/">disqus website</a> and fill your id on <code>_config.yml</code>.</li></ul>octopressDeploying Octopress on github with your domainhttps://jorge.maroto.me/deploying-octopress-on-github-with-your-domain/https://jorge.maroto.me/deploying-octopress-on-github-with-your-domain/Quick summary about how to download and deploy an octopress blog on github.Sat, 07 Sep 2013 08:01:00 GMT<p>I started to write this post because I want to have some place to remember how to install (quickly) another octopress, and I'm too lazy to read again all the documentation.</p><p>I followed steps explained on <a href="http://octopress.org/docs/setup/">Octopress documentation</a>, but mainly it consists on clone Octopress repo and install required gems:</p><pre><code class="language-bash">git clone git://github.com/imathis/octopress.git jorgemaroto.es
cd jorgemaroto.es
bundle install #</code></pre><p>After that, you need to create a repository on Github as they explain on their <a href="http://octopress.org/docs/deploying/github/">github guide</a>, you can choose between two ways.<br>In my case I going to create a repo with my name (<code>patoroco.github.io</code>), so after that I can update all the content to <strong>master branch</strong>. At this point, you can execute rake task, which will be a wizard to configure all.</p><pre><code class="language-bash">rake setup_github_pages
rake install
</code></pre><p>By default it uses classic theme, but I was looking other options, and finally I decided to use <a href="https://github.com/amelandri/darkstripes"><strong>darkstripes</strong></a> theme, so if you want to try it, follow these steps:</p><pre><code class="language-bash">git clone git://github.com/amelandri/darkstripes.git .themes/darkstripes
rake install['darkstripes'] # again, this will ask you about overriding your current theme
</code></pre><p>At this point, you can run <code>rake preview</code> on your terminal, and your site will be available on http://localhost:4000.<br>Ok, this is a good time to publish your blog, and start to share with your friends how cool you are, so first of all you need to create a new repo on your github with your username, in my case it was <a href="http://patoroco.github.io/">http://patoroco.github.io</a>. This would be enough, but I want to use myself domain, so I create a file named <code>CNAME</code> inside source folder (that's <code>jorgemaroto.es/source/CNAME</code>), with the name of my domain:</p><pre><code class="language-text">jorgemaroto.es</code></pre><p>Obviously I needed to make a change on my domain configuration, so I recommend you that check <a href="https://help.github.com/articles/setting-up-a-custom-domain-with-pages">Github Pages with custom domain</a> page, because they explain it better than me :).</p><p>Finally, you need to edit some parameters on <code>_config.yml</code> file as follows:</p><pre><code class="language-yaml">url: http://jorgemaroto.es
title: Jorge Maroto
subtitle: Trying to write a blog (again).
author: Jorge Maroto
simple_search: http://google.com/search
description: Here I'll try to write a blog somewhat more technical than in the past, and in English!</code></pre><p>After that, you can run <code>rake deploy</code>, and you can now access to your website using selected domain (it could take some hours).</p><p>It's important to highlight that with <code>rake deploy</code>, you are uploading to github static files only, so it's recommendable to push also your source files (that is markdown files, sass, etc) without compile.<br>Octopress makes it very easy because you always work on a branch named <code>source</code>, and when you deploy to <code>master</code> branch, it does that automatically, so at this point you only need to push your source branch:</p><pre><code class="language-bash">git push origin source</code></pre><p>On the next post, I'll explain which configuration I did to customize title, social networks, and other.</p>octopressgithubWhy Octopress?https://jorge.maroto.me/why-octopress/https://jorge.maroto.me/why-octopress/Here I am, trying to write a blog again. This time I hope to be more constant...Fri, 06 Sep 2013 20:01:00 GMT<p>Here I am, trying to write a blog again. This time I hope to be more constant than <a href="https://blog.patoroco.net/">last time</a>, besides trying to write in english (sorry for the spelling errors), so this is a big challenge for me.</p><p>Ok, and... why <a href="http://octopress.org/">Octopress</a>? My answer is 'why not?', I've used with Wordpress for several years, both personal as for work, and I really like it and PHP, but it was time to try another things, and I decided to start to play with Ruby, so let's say that this is a mix of all these things.</p><p>I would like to name some of the things that made me decide by octopress:</p><ul><li>My blog died. Really not, but I've been almost two years without update it, so I started to think about a change.</li><li>I want to <strong>practice and improve my english</strong>, so I decided to create a new blog, mainly in english.</li><li><strong>I like markdown</strong>, it's easy to read and edit, it's multi-platform, and exist several apps to work with it (I use Mou, because it's simple and free) and much documentation (<a href="http://daringfireball.net/projects/markdown/">Daring Fireball</a>, where markdown born).</li><li>It's a good reason to <strong>play with Ruby</strong>, even if I only edit some plugins, I'll be improving my Ruby-skills.</li><li>Octopress come from Jekyll, so it has many plugins to do easy each typical blogging task and a big <strong>community</strong>.</li><li>Finally... It's cool, and I feel like a hacker! Do you know that I can write this post from my iPhone on markdown format, share with Dropbox and deploy on github easily? Further, you can make a pull-request to improve/complete/fix any post. <strong>Kevin Mitnick would dream with this!</strong></li></ul><p>I hope to write several posts about how to install and configure Octopress, so stay tuned if you are interested in it.</p>octopress