{"id":15982,"date":"2018-09-06T11:10:20","date_gmt":"2018-09-06T09:10:20","guid":{"rendered":"https:\/\/owncloud.com\/?p=15982"},"modified":"2021-02-16T18:06:49","modified_gmt":"2021-02-16T18:06:49","slug":"docker-owncloud-traefik-reverse-proxy-lets-encrypt-ssl","status":"publish","type":"post","link":"https:\/\/owncloud.com\/de\/blogs\/docker-owncloud-traefik-reverse-proxy-lets-encrypt-ssl\/","title":{"rendered":"Docker Series Pt.2: Set up ownCloud + Traefik as a Reverse Proxy with Let&#8217;s Encrypt SSL"},"content":{"rendered":"<p>In the <a href=\"https:\/\/owncloud.com\/news\/how-to-set-up-an-owncloud-in-3-minutes\/\">first blog post<\/a> of this series you learned how to set up ownCloud with docker-compose. This tutorial builds on this knowledge to build an advanced docker setup. Docker can do far more than just setting up containers, it also makes communication between containers easier.<\/p>\n<p>A reverse proxy is useful in many ways. You can integrate multiple services easily in your setup, while they are reachable with only one public IP. It can also provide and automate Let&#8217;s Encrypt SSL certificates &#8211; for all your services.<\/p>\n<p>Using Traefik has many advantages: it is easy to set up, it has a useful web interface, and it&#8217;s specifically designed to work with docker containers.<\/p>\n<p>This guide explains how to set up Docker with Traefik and integrate an ownCloud into it. Integrating other docker images like <a href=\"https:\/\/docs.docker.com\/compose\/wordpress\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress<\/a>, <a href=\"https:\/\/github.com\/robertoandrade\/docker-jitsi-meet\" target=\"_blank\" rel=\"noopener noreferrer\">Jitsi<\/a>, <a href=\"https:\/\/github.com\/maxking\/docker-mailman\" target=\"_blank\" rel=\"noopener noreferrer\">Mailman<\/a>, or <a href=\"https:\/\/github.com\/CollaboraOnline\/Docker-CODE\" target=\"_blank\" rel=\"noopener noreferrer\">Collabora<\/a> works in a similar way&#8230; try it out and play around!<\/p>\n<h2 id=\"create-the-network\">The First Steps<\/h2>\n<p>This guide assumes that you already have docker-compose installed on your machine. If you haven&#8217;t, just follow these <a href=\"https:\/\/docs.docker.com\/compose\/install\/\" target=\"_blank\" rel=\"noopener noreferrer\">official instructions<\/a> for your operating system.<\/p>\n<p>First you have to <strong>create a network<\/strong> for all services which should be reachable from the Internet. We then need to define it outside of a docker-compose file, as we want to use it for multiple docker-compose files:<\/p>\n<pre><code><span class=\"hljs-attribute\">docker network create web<\/span>\n<\/code><\/pre>\n<p>This way, your database containers are protected. Not even Traefik can see them, they will all get their own internal network later, one for each service.<\/p>\n<p>Then we will set up our working directory. You can also use another place on the system, but then you will have to change all the paths in this guide.<\/p>\n<pre><code>mkdir -p \/opt\/traefik\ntouch \/opt\/traefik\/docker-compose.yml\ntouch \/opt\/traefik\/acme.json &amp;&amp; chmod 600 \/opt\/traefik\/acme.json\ntouch \/opt\/traefik\/traefik.toml\n<\/code><\/pre>\n<p>Let&#8217;s also assume that you have bought a domain which is pointing to the IP address of your server. Each of your services will need a subdomain, but they can all point to the same IP. Here&#8217;s an example:<\/p>\n<div id=\"attachment_16065\" style=\"width: 1042px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/owncloud.com\/wp-content\/uploads\/2018\/09\/ownCloud-docker-traefik-dns-settings.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-16065\" class=\"size-full wp-image-16065\" src=\"https:\/\/owncloud.com\/wp-content\/uploads\/2018\/09\/ownCloud-docker-traefik-dns-settings.png\" alt=\"ownCloud docker traefik dns settings\" width=\"1032\" height=\"310\" \/><\/a><p id=\"caption-attachment-16065\" class=\"wp-caption-text\">Example IPv4 DNS settings for your server<\/p><\/div>\n<p>In this guide, the domain and subdomains are <strong>example.com<\/strong>,<strong> traefik.example.com<\/strong>, and<strong> owncloud.example.com<\/strong> &#8211; you will need to exchange it with your domain name when you are copy-pasting the docker-compose and config files.<\/p>\n<h2 id=\"define-the-traefik-container\">Define the Traefik Container<\/h2>\n<p>Now we will set up Traefik. First <strong>create and edit<\/strong> the traefik docker-compose file with <code>vim \/opt\/traefik\/docker-compose.yml<\/code>:<\/p>\n<pre><code><span class=\"hljs-attribute\">version<\/span>: '2'\n\n<span class=\"elixir\"><span class=\"hljs-symbol\">services:<\/span>\n  <span class=\"hljs-symbol\">proxy:<\/span>\n    <span class=\"hljs-comment\"># You might want to use a proper version<\/span>\n    <span class=\"hljs-symbol\">image:<\/span> traefik\n    command: --configFile=\/traefik.toml\n    <span class=\"hljs-symbol\">restart:<\/span> <span class=\"hljs-keyword\">unless<\/span>-stopped\n    <span class=\"hljs-comment\"># Here's the network we created:<\/span>\n    <span class=\"hljs-symbol\">networks:<\/span>\n      - web\n    <span class=\"hljs-comment\"># The traefik entryPoints<\/span>\n    <span class=\"hljs-symbol\">ports:<\/span>\n      - <span class=\"hljs-string\">80:80<\/span>\n      - <span class=\"hljs-string\">443:443<\/span><\/span>\n<span class=\"hljs-attr\">    labels:<\/span>\n<span class=\"hljs-comment\">      - traefik.enable=true<\/span>\n<span class=\"hljs-bullet\">      -<\/span> <span class=\"hljs-string\">traefik.frontend.rule=Host:<strong>traefik.example.com<\/strong><\/span>\n      <span class=\"hljs-comment\"># Traefik will proxy to its own GUI.<\/span>\n<span class=\"hljs-bullet\">      -<\/span> <span class=\"hljs-string\">traefik.port=8080<\/span>\n      - traefik.docker.network=web\n<span class=\"elixir\">    <span class=\"hljs-symbol\">volumes:<\/span> \n      - <span class=\"hljs-regexp\">\/var\/run<\/span><span class=\"hljs-regexp\">\/docker.sock:\/var<\/span><span class=\"hljs-regexp\">\/run\/docker<\/span>.sock \n      - <span class=\"hljs-regexp\">\/opt\/traefik<\/span><span class=\"hljs-regexp\">\/traefik.toml:\/traefik<\/span>.toml \n      - <span class=\"hljs-regexp\">\/opt\/traefik<\/span><span class=\"hljs-regexp\">\/acme.json:\/acme<\/span>.json \n\n<span class=\"hljs-symbol\">networks:<\/span> \n  <span class=\"hljs-symbol\">web:<\/span> \n    <span class=\"hljs-symbol\">external:<\/span> <span class=\"hljs-keyword\">true<\/span><\/span> <\/code><\/pre>\n<p>You should of course <strong>replace example.com<\/strong> in the docker-compose file with your own domain name.<\/p>\n<h2 id=\"configure-traefik\">The Traefik Config File<\/h2>\n<p>Traefik has a toml config file to manage entry points, Let&#8217;s Encrypt settings, and the web interface. <strong>Create the traefik config file<\/strong> with <code>vim \/opt\/traefik\/traefik.toml<\/code>:<\/p>\n<pre><code><span class=\"hljs-attr\"># uncomment this line to get debug info with \"docker logs\":\n#debug<\/span> = true\n\n<span class=\"hljs-attr\">defaultEntryPoints<\/span> = [<span class=\"hljs-string\">\"https\"<\/span>,<span class=\"hljs-string\">\"http\"<\/span>]\n\n<span class=\"hljs-comment\"># The syntax is somewhat esoteric so this is mostly copy-paste<\/span>\n[entryPoints]\n  [entryPoints.http]\n  <span class=\"hljs-attr\">address<\/span> = <span class=\"hljs-string\">\":80\"<\/span>\n    [entryPoints.http.redirect]\n    <span class=\"hljs-attr\">entryPoint<\/span> = <span class=\"hljs-string\">\"https\"<\/span>\n  [entryPoints.https]\n  <span class=\"hljs-attr\">address<\/span> = <span class=\"hljs-string\">\":443\"<\/span>\n  [entryPoints.https.tls]\n\n[docker]\n<span class=\"hljs-attr\">endpoint<\/span> = <span class=\"hljs-string\">\"unix:\/\/\/var\/run\/docker.sock\"<\/span>\n<span class=\"hljs-attr\">domain<\/span> = <span class=\"hljs-string\">\"<strong>example.com<\/strong>\"<\/span>\n<span class=\"hljs-attr\">watch<\/span> = <span class=\"hljs-literal\">true<\/span>\n<span class=\"hljs-attr\">exposedbydefault<\/span> = <span class=\"hljs-literal\">false<\/span>\n\n[acme]\n<span class=\"hljs-attr\">email<\/span> = <span class=\"hljs-string\">\"<strong>youremail@example.com<\/strong>\"<\/span>\n<span class=\"hljs-attr\">storage<\/span> = <span class=\"hljs-string\">\"\/acme.json\"\n# problems with let's encrypt? You can use this staging environment, \n# if you have to do a lot of trial and error:\n#caServer = \"https:\/\/acme-staging-v02.api.letsencrypt.org\/directory\"<\/span>\n<span class=\"hljs-attr\">entryPoint<\/span> = <span class=\"hljs-string\">\"https\"<\/span>\n<span class=\"hljs-attr\">OnHostRule<\/span> = <span class=\"hljs-literal\">true<\/span>\n[acme.httpChallenge]\n<span class=\"hljs-attr\">entryPoint<\/span> = <span class=\"hljs-string\">\"http\"<\/span>\n\n<span class=\"hljs-comment\"># enable web configuration backend.<\/span>\n[web]\n\n<span class=\"hljs-comment\"># Web administration port, proxied in docker-compose.yml<\/span>\n<span class=\"hljs-attr\">address<\/span> = <span class=\"hljs-string\">\":8080\"<\/span>\n<\/code><\/pre>\n<p>You need to <strong>add your<\/strong> <strong>domain and email address<\/strong> at [docker] and [acme], so that the config file works for you. The values you have to change are in <strong>bold<\/strong>.<\/p>\n<p>This traefik.toml automatically fetches a Let&#8217;s Encrypt SSL certificate, and also redirects all unencrypted HTTP traffic to port 443. This way, no one accidentally accesses your ownCloud without encryption.<\/p>\n<p>Now we are good to go! Run the container with <code>docker-compose -f \/opt\/traefik\/docker-compose.yml up -d<\/code>. And that&#8217;s it!<\/p>\n<p>If Let&#8217;s Encrypt doesn&#8217;t work out of the box, you may have to do some troubleshooting. Note that Let&#8217;s Encrypt blocks certificate requests if you try too often; that&#8217;s why you can use the alternative caServer option in traefik.toml.<\/p>\n<p>If you uncomment it, Traefik asks the Let&#8217;s Encrypt staging server for an (untrusted) certificate. When you get that to work, you can then comment out the caServer option again, so it uses the default server for fetching trusted certificates. Good luck troubleshooting!<\/p>\n<p>If it works, you can visit <strong>traefik.example.com<\/strong> to look at the web interface. It should look like this:<\/p>\n<div id=\"attachment_16067\" style=\"width: 1914px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/owncloud.com\/wp-content\/uploads\/2018\/09\/ownCloud-docker-traefik-web-interface.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-16067\" class=\"size-full wp-image-16067\" src=\"https:\/\/owncloud.com\/wp-content\/uploads\/2018\/09\/ownCloud-docker-traefik-web-interface.jpg\" alt=\"ownCloud docker traefik web interface\" width=\"1904\" height=\"933\" \/><\/a><p id=\"caption-attachment-16067\" class=\"wp-caption-text\">The Traefik web interface with no other containers running yet.<\/p><\/div>\n<h3 id=\"basic-authentication-for-traefik-\">Add Basic Authentication for Traefik<\/h3>\n<p>If you want to expose the Traefik web interface, you would probably like to have some form of authentication. Basic auth is supported so let&#8217;s add that. Run this for the username you want &#8211; for example admin &#8211; and enter your password. It will compute a hash of the password, which you can use in the docker-compose file:<\/p>\n<pre><code><span class=\"hljs-attribute\">htpasswd -n username<\/span>\n<\/code><\/pre>\n<p>Here&#8217;s what I got for admin\/admin:<\/p>\n<pre><code>admin:<span class=\"hljs-variable\">$apr1<\/span><span class=\"hljs-variable\">$IBj9Hfsd<\/span><span class=\"hljs-variable\">$kf7vXLpY4<\/span><span class=\"hljs-regexp\">\/9XD365jcp\/<\/span>n1\n<\/code><\/pre>\n<p>(<strong>Don&#8217;t use admin\/admin as a password combination.<\/strong> Every hacker tries that first.)<\/p>\n<p>Now that needs to go in the docker-compose.yml. <strong>Add this to the labels-section<\/strong>: (<strong>Note:<\/strong> any $ signs have to be escaped with another $.)<\/p>\n<pre><code>\u00a0   labels:\n      - <span class=\"hljs-string\">\"traefik.frontend.auth.basic=admin:$<span class=\"hljs-variable\">$apr1<\/span>$<span class=\"hljs-variable\">$IBj9Hfsd<\/span>$<span class=\"hljs-variable\">$kf7vXLpY4<\/span>\/9XD365jcp\/n1\"<\/span><\/code><\/pre>\n<p><strong>Rebuild your container<\/strong> with <code>docker-compose -f \/opt\/traefik\/docker-compose.yml up -d<\/code> and now you should have basic auth! Just visit <strong>traefik.example.com<\/strong> again &#8211; and you will be prompted for a password.<\/p>\n<p>Now you have a running Traefik container, with a secured web interface, where you can watch the containers that Traefik is handling.<\/p>\n<h2 id=\"add-the-owncloud-containers\">Add the ownCloud Containers<\/h2>\n<p>Now let&#8217;s add an ownCloud to this setup. We&#8217;ve already covered the ownCloud docker-compose file in the last blogpost, biut now you will learn how to integrate it here.<\/p>\n<p>First, <strong>create a folder<\/strong> for ownCloud and <strong>edit the docker-compose.yml<\/strong> with<\/p>\n<pre><code><span class=\"hljs-built_in\">mkdir<\/span> \/opt\/ownCloud\n<span class=\"hljs-keyword\">vim<\/span> \/opt\/ownCloud\/docker-compose.yml\n<\/code><\/pre>\n<p>You can use this as an example, but you should use your own domain instead of <strong>example.com <\/strong>and change any insecure default passwords. Everything you have to change is in <strong>bold<\/strong> here:<\/p>\n<pre><code><span class=\"hljs-attribute\">version<\/span>: '2.1'\n\n<span class=\"haml\">volumes:\n  files:\n    driver: local\n  mysql:\n    driver: local\n  backup:\n    driver: local\n  redis:\n    driver: local\n\nservices:\n  owncloud:\n    image: owncloud\/server:10.0\n    restart: unless-stopped\n    depends_on:\n      -<span class=\"ruby\"> db\n<\/span>      -<span class=\"ruby\"> redis\n<\/span>    environment:\n      -<span class=\"ruby\"> OWNCLOUD_DOMAIN=<strong>owncloud.example.com\n<\/strong><\/span>      -<span class=\"ruby\"> OWNCLOUD_DB_TYPE=mysql\n<\/span>      -<span class=\"ruby\"> OWNCLOUD_DB_NAME=owncloud\n<\/span>      -<span class=\"ruby\"> OWNCLOUD_DB_USERNAME=owncloud\n<\/span>      -<span class=\"ruby\"> OWNCLOUD_DB_PASSWORD=<strong>owncloud\n<\/strong><\/span>      -<span class=\"ruby\"> OWNCLOUD_DB_HOST=db\n<\/span>      -<span class=\"ruby\"> OWNCLOUD_ADMIN_USERNAME=<strong>admin\n<\/strong><\/span>      -<span class=\"ruby\"> OWNCLOUD_ADMIN_PASSWORD=<strong>admin\n<\/strong><\/span>      -<span class=\"ruby\"> OWNCLOUD_UTF8MB4_ENABLED=<span class=\"hljs-literal\">true<\/span>\n<\/span>      -<span class=\"ruby\"> OWNCLOUD_REDIS_ENABLED=<span class=\"hljs-literal\">true<\/span>\n<\/span>      -<span class=\"ruby\"> OWNCLOUD_REDIS_HOST=redis\n<\/span>    networks:\n      -<span class=\"ruby\"> web\n<\/span>      -<span class=\"ruby\"> internal\n<\/span>    labels:\n      -<span class=\"ruby\"> <span class=\"hljs-string\">traefik.enable=true<\/span>\n<\/span>      -<span class=\"ruby\"> <span class=\"hljs-string\">traefik.frontend.rule=Host:<strong>owncloud.example.com<\/strong><\/span>\n<\/span>      -<span class=\"ruby\"> <span class=\"hljs-string\">traefik.port=80<\/span>\n<\/span>      -<span class=\"ruby\"> <span class=\"hljs-string\">traefik.docker.network=web<\/span>\n<\/span>    healthcheck:\n      test: [\"CMD\", \"\/usr\/bin\/healthcheck\"]\n      interval: 30s\n      timeout: 10s\n      retries: 5\n    volumes:\n      -<span class=\"ruby\"> <span class=\"hljs-symbol\">files:<\/span>\/mnt\/data\n<\/span>\n  db:\n    image: webhippie\/mariadb:latest\n    restart: unless-stopped\n    environment:\n      -<span class=\"ruby\"> MARIADB_ROOT_PASSWORD=<strong>owncloud\n<\/strong><\/span>      -<span class=\"ruby\"> MARIADB_USERNAME=owncloud\n<\/span>      -<span class=\"ruby\"> MARIADB_PASSWORD=<strong>owncloud\n<\/strong><\/span>      -<span class=\"ruby\"> MARIADB_DATABASE=owncloud\n<\/span>      -<span class=\"ruby\"> MARIADB_MAX_ALLOWED_PACKET=<span class=\"hljs-number\">128<\/span>M\n<\/span>      -<span class=\"ruby\"> MARIADB_INNODB_LOG_FILE_SIZE=<span class=\"hljs-number\">64<\/span>M\n<\/span>      -<span class=\"ruby\"> MARIADB_INNODB_LARGE_PREFIX=ON\n<\/span>      -<span class=\"ruby\"> MARIADB_INNODB_FILE_FORMAT=Barracuda\n<\/span>    healthcheck:\n      test: [\"CMD\", \"\/usr\/bin\/healthcheck\"]\n      interval: 30s\n      timeout: 10s\n      retries: 5\n    volumes:\n      -<span class=\"ruby\"> <span class=\"hljs-symbol\">mysql:<\/span>\/var\/lib\/mysql\n<\/span>      -<span class=\"ruby\"> <span class=\"hljs-symbol\">backup:<\/span>\/var\/lib\/backup\n<\/span>    networks:\n      -<span class=\"ruby\"> internal\n<\/span>\n  redis:\n    image: webhippie\/redis:latest\n    restart: unless-stopped\n    environment:\n      -<span class=\"ruby\"> REDIS_DATABASES=<span class=\"hljs-number\">1<\/span>\n<\/span>    healthcheck:\n      test: [\"CMD\", \"\/usr\/bin\/healthcheck\"]\n      interval: 30s\n      timeout: 10s\n      retries: 5\n    volumes:\n      -<span class=\"ruby\"> <span class=\"hljs-symbol\">redis:<\/span>\/var\/lib\/redis\n<\/span>    networks:\n      -<span class=\"ruby\"> internal\n<\/span>\nnetworks:\n  web:\n    external: true\n  internal:<\/span>\n<\/code><\/pre>\n<p>If you read carefully, you will notice that we only expose port 80 for the ownCloud container. How does this fit with using SSL certificates?<\/p>\n<p>Well, the ownCloud container does not communicate with the outside at all &#8211; only with the Traefik container. Traefik does not need to encrypt the traffic to the ownCloud container and vice versa, they are on the same machine anyway. As Traefik handles the SSL encryption, ownCloud does not even need to know that users are accessing it encrypted.<\/p>\n<p>You can <strong>run the container<\/strong> with <code>docker-compose -f \/opt\/ownCloud\/docker-compose.yml up -d<\/code> and then ownCloud starts! As soon as the health test at <code>docker ps<\/code> shows the ownCloud container as being healthy, Traefik will start routing to it. You can check if your ownCloud works at <strong>owncloud.example.com<\/strong>.<\/p>\n<p>Congratulations! You just set up ownCloud with Traefik. What&#8217;s next?<\/p>\n<h2 id=\"play-around-with-docker-\">Play Around with Docker!<\/h2>\n<p>You can also add other services like, as we already mentioned, <a href=\"https:\/\/docs.docker.com\/compose\/wordpress\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress<\/a>, <a href=\"https:\/\/github.com\/robertoandrade\/docker-jitsi-meet\" target=\"_blank\" rel=\"noopener noreferrer\">Jitsi<\/a>, <a href=\"https:\/\/github.com\/maxking\/docker-mailman\" target=\"_blank\" rel=\"noopener noreferrer\">Mailman<\/a>, and <a href=\"https:\/\/github.com\/CollaboraOnline\/Docker-CODE\" target=\"_blank\" rel=\"noopener noreferrer\">Collabora<\/a>, but there are also hundreds of others to choose from. All of them are only a container away.<\/p>\n<p>When you have integrated some services and have a cool docker-compose file for your setup, why not share it, so that everyone can learn from it? This way, others have an easier time setting it up &#8211; or can point out where you can improve your setup.<\/p>\n<p style=\"text-align: center;\">\n  <div class=\"button-block button-block--center\">\n    <a href=\"https:\/\/central.owncloud.org\/c\/server\" class=\"button button--bright-blue\" target=\"_blank\" rel=\"noopener noreferrer\">\n              <i class=\"fa-comment\">&nbsp;&nbsp;<\/i>\n            Share your setup on Central!    <\/a>\n  <\/div>\n\n  <\/p>\n<p>Did you encounter problems with this guide? You can always ask in the comments for advice. And if you made it through this how-to easily, share your success on social media!<\/p>\n<p>A big warm thank you to Jon Neverland for his blogpost <a href=\"https:\/\/jonnev.se\/traefik-with-docker-and-lets-encrypt\/\" target=\"_blank\" rel=\"noopener noreferrer\">Traefik with Docker and Let&#8217;s encrypt<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Docker is an easy and powerful way to set up ownCloud, making it easy to extend the architecture. The reverse proxy Traefik, for example, integrates other services and can provide Let&#8217;s Encrypt SSL certificates.<\/p>\n","protected":false},"author":7,"featured_media":16082,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","inline_featured_image":false,"footnotes":""},"categories":[48],"tags":[229,225,388,352,349,487],"class_list":["post-15982","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","tag-collabora","tag-community","tag-docker","tag-opensource","tag-server","tag-traefik"],"acf":[],"_links":{"self":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts\/15982","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/comments?post=15982"}],"version-history":[{"count":1,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts\/15982\/revisions"}],"predecessor-version":[{"id":59156,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts\/15982\/revisions\/59156"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/media\/16082"}],"wp:attachment":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/media?parent=15982"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/categories?post=15982"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/tags?post=15982"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}