Skip to main content

the avatar of Federico Mena-Quintero

Propagating Errors

Lately, I have been converting the code in librsvg that handles XML from C to Rust. For many technical reasons, the library still uses libxml2, GNOME's historic XML parsing library, but some of the callbacks to handle XML events like start_element, end_element, characters, are now implemented in Rust. This has meant that I'm running into all the cases where the original C code in librsvg failed to handle errors properly; Rust really makes it obvious when that happens.

In this post I want to talk a bit about propagating errors. You call a function, it returns an error, and then what?

What can fail?

It turns out that this question is highly context-dependent. Let's say a program is starting up and tries to read a configuration file. What could go wrong?

  • The file doesn't exist. Maybe it is the very first time the program is run, and so there isn't a configuration file at all? Can the program provide a default configuration in this case? Or does it absolutely need a pre-written configuration file to be somewhere?

  • The file can't be parsed. Should the program warn the user and exit, or should it revert to a default configuration (should it overwrite the file with valid, default values)? Can the program warn the user, or is it a user-less program that at best can just shout into the void of a server-side log file?

  • The file can be parsed, but the values are invalid. Same questions as the case above.

  • Etcetera.

At each stage, the code will probably see very low-level errors ("file not found", "I/O error", "parsing failed", "value is out of range"). What the code decides to do, or what it is able to do at any particular stage, depends both on the semantics you want from the program, and from the code structure itself.

Structuring the problem

This is an easy, but very coarse way of handling things:

gboolean
read_configuration (const char *config_file_name)
{
    /* open the file */

    /* parse it */

    /* set global variables to the configuration values */

    /* return true if success, or false if failure */
}

What is bad about this? Let's see:

  • The calling code just gets a success/failure condition. In the case of failure, it doesn't get to know why things failed.

  • If the function sets global variables with configuration values as they get read... and something goes wrong and the function returns an error... the caller ends up possibly in an inconsistent state, with a set of configuration variables that are only halfway-set.

  • If the function finds parse errors, well, do you really want to call UI code from inside it? The caller might be a better place to make that decision.

A slightly better structure

Let's add an enumeration to indicate the possible errors, and a structure of configuration values.

enum ConfigError {
    ConfigFileDoesntExist,
    ParseError, // config file has bad syntax or something
    ValueError, // config file has an invalid value
}

struct ConfigValues {
    // a bunch of fields here with the program's configuration
}

fn read_configuration(filename: &Path) -> Result<ConfigValues, ConfigError> {
    // open the file, or return Err(ConfigError::ConfigFileDoesntExist)

    // parse the file; or return Err(ConfigError::ParseError)

    // validate the values, or return Err(ConfigError::ValueError)

    // if everything succeeds, return Ok(ConfigValues)
}

This is better, in that the caller decides what to do with the validated ConfigValues: maybe it can just copy them to the program's global variables for configuration.

However, this scheme doesn't give the caller all the information it would like to present a really good error message. For example, the caller will get to know if there is a parse error, but it doesn't know specifically what failed during parsing. Similarly, it will just get to know if there was an invalid value, but not which one.

Ah, so the problem is fractal

We could have new structs to represent the little errors, and then make them part of the original error enum:

struct ParseError {
    line: usize,
    column: usize,
    error_reason: String,
}

struct ValueError {
    config_key: String,
    error_reason: String,
}

enum ConfigError {
    ConfigFileDoesntExist,
    ParseError(ParseError), // we put those structs in here
    ValueError(ValueError),
}

Is that enough? It depends.

The ParseError and ValueError structs have individual error_reason fields, which are strings. Presumably, one could have a ParseError with error_reason = "unexpected token", or a ValueError with error_reason = "cannot be a negative number".

One problem with this is that if the low-level errors come with error messages in English, then the caller has to know how to localize them to the user's language. Also, if they don't have a machine-readable error code, then the calling code may not have enough information to decide what do do with the error.

Let's say we had a ParseErrorKind enum with variants like UnexpectedToken, EndOfFile, etc. This is fine; it lets the calling code know the reason for the error. Also, there can be a gimme_localized_error_message() method for that particular type of error.

enum ParseErrorKind {
    UnexpectedToken,
    EndOfFile,
    MissingComma,
    // ... etc.
}

struct ParseError {
    line: usize,
    column: usize,
    kind: ParseErrorKind,
}

How can we expand this? Maybe the ParseErrorKind::UnexpectedToken variant wants to contain data that indicates which token it got that was wrong, so it would be UnexpectedToken(String) or something similar.

But is that useful to the calling code? For our example program, which is reading a configuration file... it probably only needs to know if it could parse the file, but maybe it doesn't really need any additional details on the reason for the parse error, other than having something useful to present to the user. Whether it is appropriate to burden the user with the actual details... does the app expect to make it the user's job to fix broken configuration files? Yes for a web server, where the user is a sysadmin; probably not for a random end-user graphical app, where people shouldn't need to write configuration files by hand in the first place (should those have a "Details" section in the error message window? I don't know!).

Maybe the low-level parsing/validation code can emit those detailed errors. But how can we propagate them to something more useful to the upper layers of the code?

Translation and propagation

Maybe our original read_configuration() function can translate the low-level errors into high-level ones:

fn read_configuration(filename: &Path) -> Result<ConfigValues, ConfigError> {
    // open file

    if cannot_open_file {
        return Err(ConfigError::ConfigFileDoesntExist);
    }

    let contents = read_the_file().map_err(|e| ... oops, maybe we need an IoError case, too)?;

    // parse file

    let parsed = parse(contents).map_err(|e| ... translate to a higher-level error)?

    // validate

    let validated = validate(parsed).map_err(|e| ... translate to a higher-level error)?;

    // yay!
    Ok(ConfigValues::from(validated))
}

Etcetera. It is up to each part of the code to decide what do do with lower-level errors. Can it recover from them? Should it fail the whole operation and return a higher-level error? Should it warn the user right there?

Language facilities

C makes it really easy to ignore errors, and pretty hard to present detailed errors like the above. One could mimic what Rust is actually doing with a collection of union and struct and enum, but this gets very awkward very fast.

Rust provides these facilities at the language level, and the idioms around Result and error handling are very nice to use. There are even crates like failure that go a long way towards automating error translation, propagation, and conversion to strings for presenting to users.

Infinite details

I've been recommending The Error Model to anyone who comes into a discussion of error handling in programming languages. It's a long, detailed, but very enlightening read on recoverable vs. unrecoverable errors, simple error codes vs. exceptions vs. monadic results, the performance/reliability/ease of use of each model... Definitely worth a read.

the avatar of Nathan Wolf

the avatar of Nathan Wolf

the avatar of Santiago Zarate

gentoo eix-update failure

Summary

If you are having the following error on your Gentoo system:

 Can't open the database file '/var/cache/eix/portage.eix' for writing (mode = 'wb') 

Don’t waste your time, simply the /var/cache/eix directory is not present and/or writeable by the eix/portage use

mkdir -p /var/cache/eix
chmod +w /var/cache/eix*

Basic story is that eix will drop privileges to portage user when ran as root.

a silhouette of a person's head and shoulders, used as a default avatar

GSoC 2018 Mentor Summit

David Kang and I attended two weeks ago (12-14 Oct) the Google Summer of Code (GSoC) Mentor Summit in California representing openSUSE. :sunny: Here is our report of the conference.

It was an incredibly well organized event with a busy schedule. It was our first summit (we try that different openSUSE mentors/org admins go every year) and we enjoyed it a lot and found it really useful. Apart from attending many sessions about open source, mentoring and GSoC, we had the opportunity to meet and have interesting conversations with other org admins and mentors, as well as with the Google open source team and other Googlers. In total 314 mentors and org admins from 42 countries attended the events. This was a great chance to collect chocolate from all around the world for the chocolate bar table, which has already become a tradition at the summit. :chocolate_bar:

chocolate table David and Ana in San Francisco

The summit follows the unconference format, which means that the sessions are decided and organized by the attendees. Those are the most outstanding sessions from the ones David and I attended:

Lightning talks

There were about 2 hours reserved for 3 minutes lightning talks, in which around 50 different organization presented their students’ work. The only rule was that the part about the organization itself couldn’t be longer than 1 minute (ideally 30 seconds). We liked the original idea of clapping when the 3 minutes were over to avoid that the speaker continue speaking - we should steal it for the Lightningbeers in the next openSUSE conference :wink:

There were a lot of great talks about successful histories. I especially liked the ones where the students themselves presented their work in a video. I gave a talk focused on the feedback we gave to all our students, including rejected and unsubmitted proposals, and how we try to bring those students in our community and encourage them to keep contributing. I was not sure if the talk was appropriated, taking into account that the rest of the talks were about the students’ projects. But many people come to me after the talk to say they liked it a lot and got some ideas for next year, so it seems it was. :smile:

You can find the slides of all the given lightning talks (including mines) in this Google Drive folder.

GSoD

Google is considering starting a new mentoring program: Google Season of Docs, the “GSoC for Documentation”. It was discussed whether mentoring orgs would be interested in a program of this kind and Google asked for feedback on the idea.

Apart from the fact that the program would be focused on documentation and not on code, there are other important differences. The participants would be experience technical writers (>1 year experience) and not students. As it is expected that the participants already have a full time job, the commitment would be less (~10 hours a week). Because of the same reason, the technical writers wouldn’t receive any stipend, as the students do. According to the Google team, it would be the experience they would gain though GSoD and not the money which would motivate them to participate. This was the most unclear and longest discussed part.

Recruiting, motivating and retaining mentors to your org

I found this a very appealing session, as the number of mentors in openSUSE has decreased this year to the point that we considered not to participate in GSoC due to the lack of mentors/projects. (Maybe someone reading this wants to get involved next year? - Just write me an email, comment in this blog post or check openSUSE mentoring page!)

The session was driven by Martin from Jenkins, and it was a enriching conversation between different orgs, which presented their problems, solutions and asked questions.It was curious how similar the difficulties of openSUSE and Fedora are (although not surprisingly because of the similarities of the two projects). Both communities are big and diverse, but they do not manage to get a lot of mentors involved in GSoC. Some people gave us some ideas, such as introducing non-technical mentors and having at least 2 mentors per project, but I still don’t have the feeling we found the magic solution. :sweat:

Notes of the session can be found in this Google document.

Patch Rewards

Aleksandr Dobkin, from Google, gave a talk about the Patch Reward Program, which rewards proactive security improvements in several open source projects like Chromium and Angular. Rewards for qualifying submissions range from from 500$ to 20000$, depending on the complexity and impact of the patch. In the future, they want to expand the list of in-scope projects and define specifics tasks and bounties for them.

Life after GSoC

The Googlers Cat and Josh led this session, in which we did some brainstorming and listen to other organizations’ experiences. David found interesting that most of the attendees agreed that responsibilities need to be given to the students in order to keep them motivated and engaged with the project.

Notes of the session can be found in this Google document.

Open Source Licensing

This session was supposed to be hold by the Googler Hilary Richardson, but she arrived late and it ended being a shared session with the Software Freedom Conservancy. It was an introduction to licenses, but although I had expected it to be more advance, there was some topics (some of which came up thanks to audience questions) which I didn’t know about and which I found interesting. For example, that you shouldn’t use the WTFPL (Do What the Fuck You Want To Public License) as it doesn’t include no-warranty disclaimer.

Spanish mentors meet-up

There was a meet-up of GSoC Spanish mentors and as both David and I are from Spain, we couldn’t miss it. We presented our projects, spoke about things we are doing to spread open source in Spain, such as talks at universities, and discussed what else could be done. We set a mailing list up to keep sharing ideas, material, etc.

GSoC Feedback

Google open source team organized a session where the mentors and org admin could give them feedback about things that could be improved. I suggested something that openSUSE Asian community suggested to me in the last openSUSE.Asia: creating a poster which summarize the reasons to become a GSoC mentor and that should ideally include some visual reinforcement (like an infographic). It should catch people attention so that non-native speakers get interested enough to read the extensive documentation. (BTW, there are two videos from Google in that direction: Organizations Apply and Being a Great Google Summer of Code Mentor). I also suggested that it is clarified in the GSoC documentation that mentors and org admins are volunteers, as we had cases were students were unpolite or impatient and I think it was because they don’t know the conditions in which the mentors are helping them.

Notes of the session can be found in this Google document.

Beyond GSoC: how can Google help open source?

Google wanted to know what else they can do for open source. Most of the requests were related to founding and cloud credits. I used the opportunity to ask for a plain text option in the Gmail Android client which allows me to write to this mailing list with my phone (I know there are other clients…) and to mention the poster again when other people requested help from Google to recruit mentors.

Notes of the session can be found in this Google document.

Improving mentor/mentee relations

This session was about how to improve the relationships between mentors and mentees, potentiating engagement after GSoC. Most of the attendees were org admins and they gave us some tips to help mentees to get involved in the community and also to improve the communication with his mentor. Some of the concrete suggestions were:

  • Make everything public (conversation with the mentor, doubts, discussion, etc.) using the IRC channel.
  • Have regular meetings, at least 1 per week.
  • Set availability time box of the mentor/mentee.
  • Encourage to ask first to the community.

Open Source Metrics

It was a really cool session by CHAOSS and Google about measuring all data we can and how to turn the numbers into something useful. For instance, it was interesting the discussion about how to measure the open source culture in a project: how many people say thank you, time to answer, PRs and issues closed, etc. I also liked some of the original examples presented by Felipe Hoffa (Developer Advocate at Google) such as using number of page visits vs StackOverflow questions. I recommend to check the fhoffa/analyzing_github repository.

Notes of the session can be found in this Google document.

Post-mortem: why a student fail? Hear from an student and org admin

Emmanuel from Public Lab told us about his experience when he was a GSoC student and why he succeeded the first year and why not in the second year. The difference was that he had a good guidance: his mentor was very accessible and close to him. The second time, the communication was bad: he didn’t receive any warning about doing something wrong and his mentor wasn’t there for him when he needs him. After all, he ended being a successful GSoC mentor.

Failing students

It was a conversation trying to answer questions like: Why and how fail a student? How do you protect the future reputation of the student? What to do when the problem is the mentor?

We spoke about problems with really difficult solution and it was inspiring to hear other people approaches and ideas. Something that I found useful for us was the fact that some orgs are enforcing having 3 mentors per project. I think it is a good recommendation as it can save a lot of troubles from the admins perspective, it is good for the student and more fun for the mentors. However, I think we should enforce 2 mentors, but not 3. If the mentors think it is doable with 2 mentors, we should trust them. It would anyway be difficult to get 3 mentors for some of the project. Another great idea is that, in case the mentors disappear by any reason and you don’t know where to get more mentors from, write the GSoC mailing list. There are a lot of people working in diverse projects and someone may be able to help.

Notes of the session can be found in this Google document.

Quality of the software, when should we release?

This session was held by people from MuseScore, who wanted to discuss when a product is good enough to release. One of procedures that David founded interesting two approaches mentioned to release:

  • Time box: having a LTS version (~ 1 year) and a monthly one. The monthly one includes the most recent changes although the bugs are also backported to the LTS version. (Tumbleweed vs Leap :stuck_out_tongue_winking_eye:)
  • Feature based

Burnout

In this session, conducted by Valorie from KDE, we discussed how to identify a burnout in others and in ourselves and what to do when it happens (in general and in the GSoC context). Burnout is severe and we need to help our colleagues/mentors if we realise of it (signs: stressed, angry, grumpy, territorial, drowsy) and to step out when it happens to us (if it is important someone else will do it).

Suggestions for next year

All in all, those are my suggestions for next GSoC (they come from diverse places: the sessions, conversations with other people, etc.), in case openSUSE participates again (I hope so :wink:):

  • Make a call for mentors sharing the video and other material from Google
  • Make compulsory to have at least two mentors per project. It is more fun and secure (in case the mentor disappear for any reason, the organization need to look for another mentor)
  • For projects too specialized or which require concrete knowledge, ask for a third person who could help with the mentoring in case something happens (just as backup and not being compulsory).
  • Make compulsory that the students blog posts have a CC license (preferably CC-BY)
  • Encourage collaboration between students and mentors in the same org, for example doing video conference with several students working in similar projects.
  • Ask the mentors to complete evaluations 24 before the evaluation closes. This way the admins can complete the evaluation in the last day if the mentors haven’t done it.

Hope you have enjoyed reading the report. Remember that if you want to mentor next year in GSoC, you are more than welcome! Just write me an email, comment in this blog post or check openSUSE mentoring page.

About me

My name is Ana and I am mentor and organization admin for openSUSE at GSoC, openSUSE Board member, Open Build Service Frontend Engineer at SUSE and open source contributor in projects inside and outside openSUSE.

the avatar of Santiago Zarate

Setting up postfix, dovecot and sieve

The horror

While trying to set up my mail system, I ran into multiple tutorials to figure out what was the best way to avoid multiple error messages, mainly because you, like me (you silly human!), simply copy and pasted random stuff from stack overflow, and tutorials in howtoforge and places like that…

The mistakes

You tried something like this

spamassassin unix - n n - - pipe flags=DROhu user=vmail argv=/usr/bin/spamc -e /usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} 

or this:

mailbox_transport = lmtp:unix:private/lmtp
virtual_transport = lmtp:unix:private/lmtp

The pain

so you ended up with something that looks similar to this:

Oct 24 01:13:24 nergal postfix/pipe[10207]: fatal: get_service_attr: unknown username: vmail
Oct 24 01:13:25 nergal postfix/master[10104]: warning: process /usr/lib/postfix/bin//pipe pid 10207 exit status 1
Oct 24 01:13:25 nergal postfix/qmgr[10106]: warning: private/spamassassin socket: malformed response
Oct 24 01:13:25 nergal postfix/master[10104]: warning: /usr/lib/postfix/bin//pipe: bad command startup -- throttling
Oct 24 01:13:25 nergal postfix/qmgr[10106]: warning: transport spamassassin failure -- see a previous warning/fatal/panic logfile record for the problem description

Resignation

So what worked for me was to leave the service in the master.cf as I had it working…

and simply add to master.cf

spamassassin unix - n   n - - pipe flags=R     user=app argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

and in the main.cf

mailbox_command = /usr/lib/dovecot/deliver

The light

Sieve filtering started to work after these changes :)

the avatar of Santiago Zarate

Visa, Venezuela, Prorroga

Como renovar visa como Venezolano con prorroga y no morir en el intento

Si llegaste hasta este lugar, es porque eres posiblemente Venezolano, y estas en la penosa necesidad de necesitar una prorroga, pero tambien debes renovar tu visa de residente sea en el pais que estes.

Ya que no encontre informacion clara de el proceso, aca dejo los pasos que tuve que seguir en Alemania:

  1. Solicitar la prorroga en la pagina de Saime, y pagar el monto.
  2. Mientras llega la prorroga, llama a la embajada de Venezuela que te corresponde y solicita una constancia de tramite de prorroga.
  3. Comunicate con la autoridad de migracion de el pais donde necesites renovar tu visa, y solicita la extension de tu visa, asegurate de entregar la constancia de que estas tramitando tu prorroga.
  4. En el transcurso del tiempo entre que solicitas la cita para extender tu visa, y el momento de la cita, puede ser que la prorroga te llegue, aparecete en la cita con tu flamante prorroga, si esta no llega, te otorgaran un permiso temporal, mientras te llega la prorroga, una vez que te llegue, dirigete al paso 3.
  5. Disfrute de dos años mas de estancia :)

Cuanto tiempo toma?

Entropia. No estoy seguro de cuanto tiempo toma, hay personas a las que le toma un par de meses, y a otros les toma 3-6 meses… asi que a esperar.

No se como solicitar la prorroga!

Una explicacion flash: Una vez que ingreses con tu usuario y contraseña en la pagina de saime:

  1. Situate en la opcion “En el extranjero” - Paso 1
  2. Mueve el mouse (Horizontalmente funciona bastante bien) hacia la opcion: “Obtencion de prorroga de pasaporte electronico” paso 2
  3. Luego de ver un anuncio sobre la prorroa, deberias poder ver esto: paso 3
  4. En caso de que los pasos arriba mencionados no funcionen, una vez que logres ingresar a la web de saime con tu usuario y contraseña, puedes intentar esta url directamente: https://tramites.saime.gob.ve/index.php?r=inicio/inicio/prorrogaconsular

Si tienes alguna duda, puedes escribirme a @foursixnine en instagram o en twitter, o en ‘i+blog @ foursixnine punto io’

a silhouette of a person's head and shoulders, used as a default avatar

Flashing our way to polaris.

I have just added Sea Island support to flashrom. This puts the R600 style SPI interface behind a pair of indexed registers, but otherwise is highly compatible.

While only tested on the first Sea-Island type SPI interface (Bonaire), support should work for everything up to and including Polaris, for a grand total of 240 devices supported today.

Bonaire was the introduction of this relocated register interface. Sadly there was an issue with this chip. There are 256bytes of SPI data registers, but registers 0xd8 through 0xE8 shifted up 0x10. There's an ugly work-around for that, but it works fine and the bit of extra cpu overhead is not an issue with a slowish interface like SPI. This shift was fixed for the next ASIC though, and Hawaii no longer needs that workaround.

As for my ordered hw...
* I still need to get a Tahiti/Hainan or Oland. So there are a few dozen Southern Islands cards to be added still.
* The HD4650 i ordered turned out to be an HD2600. The seller mistook one club3d card for another with the same passive cooler. He did not bother to even compare the connectors :(
* I did get a passive X300 (rv370) and X1300 (rv515) for which i will start REing now, so that i can extend flashrom support to all PCIE devices.

As always, the code is available here.
the avatar of Klaas Freitag

Kraft Version 0.82

Vor wenigen Tagen ist die Kraft Version 0.82 erschienen.

Es handelt sich um ein weiteres Bugfix-Release zu Kraft 0.80, es enthält aber zusätzlich einige Features, die von Benutzern angefragt wurden.

Es wurden folgende Probleme gelöst:

  • „Dokument per Email versenden“ ist repariert.
  • Falsche Verwendung von einer Lokalisierungsfunktion hat für falsche Übersetzungen und Fehlermeldungen auf der Konsole gesorgt. Das wurde beseitigt.
  • Die Nachfrage, ob Änderungen am Katalog verworfen werden sollen, wurde repariert.
  • Einige Fehler im Setup-Code von Kraft wurden beseitigt.
  • Viele weitere, kleine Verbesserungen.

Folgende neue Features wurden implementiert:

  • Zusätzlich zu Thunderbird kann Email nun über das Tool xdg-email versendet werden, um andere EMail-Clients wie KMail zu unterstützen. Um xdg-email zu verwenden, muss in der Kraft-Konfigurationsdatei im Abschnitt [system] folgender Wert gesetzt werden: mailUA=xdg.
  • Der Kalkulations-Dialog für Vorlagen wurde überarbeitet. Elemente ohne Funktion wurden beseitigt und das Benutzer-Interface wurde verbessert.
  • Zeit-Kalkulationen können in Vorlagen jetzt feiner geplant werden. Dazu ist in der Zeitkalkulation die Zeit-Einheit jetzt einstellbar und nicht mehr fix auf Minuten eingestellt.

Wir freuen uns über jede Anregung zu Kraft. Fehlermeldungen und Verbesserungsvorschläge werden über den Github Issue Tracker entgegengenommen.

Viele Erfolg mit Kraft!

a silhouette of a person's head and shoulders, used as a default avatar

Current (10/2018) Tumbleweed on Raspberry Pi 1

Hallo,

I just had a little struggle getting the current tumbleweed to run on the original Raspberry Pi (first generation, though the revision with larger RAM).

Just in case this helps anybody: I did not have any luck with a fresh openSUSE Tumbleweed image of one of the current arm6 builds. Don’t know why.

Here’s what I did:
– Download a pretty old known-good OpenSUSE 13.1 built by Bernhard Wiedemann

http://www.zq1.de/bernhard/linux/opensuse/raspberrypi-opensuse-latest.img.xz

Unzip, dump it to SD Card

xz -d raspberrypi-opensuse-latest.img.xz
dd if=raspberrypi-opensuse-latest.img of=/dev/mmcblk0 bs=8M

Boot up, change to text console (CTRL + ALT + F2)
Log In (root/linux)

Change Password (passwd)

nano /etc/zypp/repos.d/oss131.repo
Change baseurl line to
baseurl=http:/download.opensuse.org/ports/armv6hl/tumbleweed/repo/oss/
Save and get out (CTRL+X, Y)

#Resize partition and FS as this build won’t do:
# Adjust to more if your card is larger or to less if you need a more advanced partitioning scheme

parted resize 3 16G

resize2fs /dev/mmcblk0p3

zypper ref

zypper up gzip rpm

zypper dup –download in-advance

#(super conservative, get all needed packages first) – This is going to take quite a while

reboot, power cycle

Note that you will end up with a system booting into X11 login. You should probably change the default systemd target and maybe also get rid of some software. And you really don’t want a server with ssh password “linux”, so better don’t skip changing the PW